Python之文件处理

Python之文件处理

open操作

open(file, mode=’r’, buffering=-1, encoding=None, errors=None, newline=None, closefd=True,opener=None)

打开一个文件,返回一个文件对象(流对象)和文件描述符。打开文件失败,则返回异常

基本使用: 创建一个文件test,然后打开它,用完关闭

1
2
3
f = open('test')    # file对象
print(f.read()) # 读取文件
f.close() # 关闭文件
123
  • 在文件操作中,最常用的操作就是读和写
  • 文件访问的模式有两种:文本模式和二进制模式。不同模式下,操作函数不尽相同,表现的结果也不一样

open的参数

file: 打开或者创建的文件名.如果不指定路径,默认当前路径

mode: 文件打开模式

open函数默认是以只读文本模式打开已存在的文件

  • r:缺省的,表示只读打开, 不能使用写文件功能
    如果使用write方法,会抛出异常
    如果文件不存在,抛出FileNotFoundError异常
    示范代码:
1
2
3
f = open('test','r')
print(f.read())
f.close()
123
  • w:表示只写打开, 如果读取文件则抛出异常
    如果文件不存在,则直接创建文件
    如果文件存在,则清空文件内容
    示范代码:
1
2
3
4
5
6
7
f = open('test','w')
f.write('123')
f.close()

f = open('test','r')
print(f.read())
f.close()
123
  • x:创建并写入一个新文件,不能使用读文件功能
    如果文件不存在,创建文件,并且以只写方式打开
    如果文件存在,抛出FileExistsErroe异常
    示范代码:
1
2
3
4
5
6
7
f = open('test0','x')
f.write('qwer')
f.close()

f = open('test1','r')
print(f.read())
f.close()
abcd123www.python.org
www.magedu.com

python3
  • a:写入打开文件
    如果文件存在,只写打开,追加内容
    如果文件不存在,则创建,直写打开,追加内容
    示范代码:
1
2
3
4
5
6
7
f = open('test','a')
f.write('*******')
f.close()

f = open('test','r')
print(f.read())
f.close()
123*******
rwxa总结:
  • r是只读,w x a 都是只写
  • w x a 都可以参数新文件
  • w 不管文件存在与否,都会生成全新内容的文件
  • a 不管文件存在与否,都能在打开文件的尾部追加新内容
  • x 要求文件必须不存在,自己创建一个新文件,否则报错

  • t:文本模式
    字符流,将文件的字节按照某种字符编码理解,按照字符操作。open的默认mode就是 rt

  • b:二进制模式
    字节流,将文件按照直接理解,与字符编码无关。二进制模式操作室,直接操作使用bytes类型

示范代码:

1
2
3
4
5
6
7
8
9
10
f = open('test1','rb')   # 二进制只读
s = f.read()
print(type(s))
print(s)
f.close()

f = open('test3','wb') # IO对象
s = f.write('lpx'.encode())
print(s)
f.close()
<class 'bytes'>
b'abcd123www.python.org\r\nwww.magedu.com\r\n\r\npython3'
3
  • +: 为r、w、a、x提供缺失的读或者写功能
    获取文件对象依旧按照r、w、a、x 自己的特征
    +号不能单独使用,可以认为它是为前面的模式字符提供增强功能
1
2
3
4
f = open('test3','r+',encoding='utf8')
print(f.read())
f.write('abcdef')
f.close()
lpx

文件指针

上面的示范代码,已经说明了有一个指针

文件指针,指向当前字节位置

mode=r,指针起始在0

mode=a,指针起始在EOF

  • tell():显示指针当前位置
  • seek(offset,[,whence])
    移动文件指针位置。offest偏移多少直接,whence从哪里开始

文本模式下

  • whence 0 缺省值,表示从头开始,offest只能正整数
  • whence 1 表示从当前位置,offest只接受0
  • whence 2 表示从EOF开始,offest只就收0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# 文本模式
f = open('test','r+')
print(f.tell()) # 起始
print(f.read())
print(f.tell()) # EOF

print(f.seek(2,0))
print(f.read())
print(f.seek(0,1)) # offset 必须为 0
print(f.seek(0,2)) # offset 必须为 0
f.close()

print('*' * 10)
# 中文
f = open('test4','w+')
print(f.write("马哥教育"))
print(f.tell())
f.close()

f = open('test4','r+')
print(f.read(2))
print(f.seek(1))
print(f.tell())
# print(f.read()) # UnicodeDecodeError 当前位置不足以构成中文
print(f.seek(2))
f.close()
0
123*******
10
2
3*******
10
10
**********
4
8
马哥
1
1
2

文本模式总结:

  • whence 为1表示从当前位置开始偏移 ,但是只支持偏移0,相当于原地不动,没什么用
  • whence 为2表示从EOF开始偏移,只支持偏移0,相当于移动文件指针到EOF
  • seek 是按照字节偏移的
  • read在文本模式下是按照字符读取的

二进制模式

  • whence 0 缺省值,表示从头开始,offest只能正整数
  • whence 1 表示从当前位置,offest可正可负
  • whence 2 表示从EOF开始,offest可正可负
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 二进制模式
f = open('test4','rb+')
print(f.tell()) # 起始
print(f.read())
print(f.tell()) #
f.write(b'abc')

print('*'* 10)

print(f.seek(0)) # 起始
print(f.seek(2,1)) # 从当前指针开始,先后2
print(f.read())
print(f.seek(-2,1)) # 从当前指针开始,先前2

print('*'* 10)

print(f.seek(2,2)) # 从EOF开始,向后2
print(f.seek(0))
print(f.seek(-2,2)) # 从EOF开始,向前2
print('*'* 10)

# f.seek(-20,2) # OSError
f.close()
0
b'\xc2\xed\xb8\xe7\xbd\xcc\xd3\xfd'
8
**********
0
2
b'\xb8\xe7\xbd\xcc\xd3\xfdabc'
9
**********
13
0
9
**********

二进制模式总结:

  • 二进制模式支持任意起点的偏移,从头、从尾、从中间位置开始
  • 向后seek 可以越界,但是向前seek 时,不能越界,否则抛异常

buffering

1 表示使用缺省大小的buffer。如果是二进制模式,使用io.DEFAULT_BUFFER_SIZE值,默认是4096或者8192。
如果是文本模式,如果是终端设备,是行缓存方式,如果不是,则使用二进制模式的策略。

  • 0 只在二进制模式使用,表示关buffer
  • 1 只在文本模式使用,表示使用行缓冲。意思就是见到换行符就flush
  • 大于1 用于指定buffer的大小

buffer 缓冲区
缓冲区一个内存空间,一般来说是一个FIFO队列,到缓冲区满了或者达到阈值,数据才会flush到磁盘。

  • flush() 将缓冲区数据写入磁盘
  • close() 关闭前会调用flush()

io.DEFAULT_BUFFER_SIZE 缺省缓冲区大小,字节

  • 二进制模式
1
2
3
4
5
6
7
8
9
10

import io
f = open('test4','w+b')
print(io.DEFAULT_BUFFER_SIZE)
f.write('lvpeixin.tech'.encode())
f.seek(0)
print(f.read())
f.write('www.lvpeixin.tech'.encode())
f.flush()
f.close()
8192
b'lvpeixin.tech'
1
2
3
4
5
6
f = open('test4','w+b',4)  # 缓冲区大小
f.write(b'lpx')
f.write(b'tech')
f.seek(0)
print(f.read())
f.close()
b'lpxtech'
  • 文本模式
    buffering=1,使用行缓冲
1
2
3
4
5
6
f = open('test4','w+',1)
f.write('lpx')
f.write('lpx'*4)
f.write('\n')
f.write('Hello\nPython')
f.close()

buffering > 1,使用指定大小的缓冲区

1
2
3
4
5
6
7
8
f = open('test4','w+', 15)
f.write("mag")
f.write('edu')
f.write('Hello\n')
f.write('\nPython')
f.write('a' * (io.DEFAULT_BUFFER_SIZE - 20)) # 设置为大于1没什么用
f.write('\nwww.magedu.com/python')
f.close()

buffering=0
这是一种特殊的二进制模式。不需要内存的buffer,可以看做是一个FIFO文件

1
2
3
4
5
6
7
8
f = open('test4','wb+', 0)
f.write(b"m")
f.write(b"a")
f.write(b"g")
f.write(b"magedu"*4)
f.write(b'\n')
f.write(b'Hello\nPython')
f.close()

buffering总结

  1. 文本模式,一般都用默认缓冲区大小
  2. 二进制模式,都是一个个字节的操作,可以指定buffer的大小
  3. 一般来说,默认缓冲区大小是个比较好的选择,除非明确知道,否则不调整默认缓冲区大小
  4. 一般编程中,明确知道需要些磁盘,都会手动调用一次flush,而不是等到自动flush或者close的时候

encodeing:编码,仅文本模式使用

None 表示使用缺省编码,依赖操作系统

  • Windows下的缺省编码是 GBK
  • Linux下的缺省编码是 UTF-8

如下代码在不同操作系统下的文件编码都是不同

1
2
3
f = open('test1','w')
f.write('啊')
f.close()

其它参数

errors

什么样的编码错误将被捕获 None和strict表示有编码错误将抛出ValueError异常;ignore表示忽略

newline

  • 文本模式中,换行的转换。
  • 可以为None、’’ 空串、’\r’、’\n’、’\r\n’ 读时,None表示’\r’、’\n’、’\r\n’都被转换为’\n’;
  • ‘’表示不会自动转换通用换行符;其它合法字符表示换行符就是指定字符,就会按照指定字符分行写时,
  • None表示’\n’都会被替换为系统缺省行分隔符os.linesep;’\n’或’’表示’\n’不替换;其它合法字符表示’\n’会被替换为指定的字符

示范代码:

1
2
3
4
5
6
7
8
f = open('test','w')
f.write('python\rwww.python.org\nwww.magedu.com\r\npython3')
f.close()
newlines = [None, '', '\n', '\r\n']
for nl in newlines:
f = open('test', 'r+' , newline=nl) # 缺省替换所有换行符
print(f.readlines())
f.close()
['python\n', 'www.python.org\n', 'www.magedu.com\n', '\n', 'python3']
['python\r', 'www.python.org\r\n', 'www.magedu.com\r', '\r\n', 'python3']
['python\rwww.python.org\r\n', 'www.magedu.com\r\r\n', 'python3']
['python\rwww.python.org\r\n', 'www.magedu.com\r\r\n', 'python3']

closefd

  • 关闭文件描述符,True表示关闭它,False会再文件关闭后保持这个描述符
  • fileobj.fileno() 可以查看文件描述符

文件上下文管理

  • 对于类似于文件对象的IO对象,一般来说都需要在不使用的时候关闭、注销,以释放资源。
  • IO被打开的时候,会获得一个文件描述符。计算机资源是有限的,所以操作系统都会做限制。
  • 就是为了保护计算机的资源不要被完全耗尽,计算资源是共享的,不是独占的。
  • file.close() 方法容易被遗忘,所以,Python引入了with语句来自动帮我们调用close()方法
1
2
3
4
5
with open('test','w+') as f:
f.write("abc") # 文件只读,写入失败

# 测试f是否关闭
f.closed # f的作用域
True

上下文管理;

  1. 使用with.. as 关键字
  2. 上下文管理语句块并不会开启新的作用域
  3. with语句执行完毕后,会自动关闭文件对象
1
2


-------------本文结束感谢您的阅读-------------
0%