文件读写
读写文件之前,必须先打开文件。
打开文件
内置函数open()
用于打开文件,函数的返回值是一个文件对象,通过该对象就可以操作文件了。
第一个参数是文件的路径,必须要指定。既可以指定绝对路径也可以指定相对路径
第二个参数是文件的打开方式,默认值是'r'
,表示以只读方式打开。
其他参数都是带默认值的,可以参考官方文档。
文件的打开方式 | 说明 | 备注 |
---|---|---|
‘r’ | 以只读方式打开,只能读文件 | 文件的默认打开方式 如果文件不存在,则抛出异常FileFoundError |
‘w’ | 以只写方式打开,只能写文件 | 如果文件存在,则清空文件 如果文件不存在,则创建文件 |
‘a’ | 以追加方式打开,只能写文件 | 如果文件存在,则从文件末尾开始写 如果文件不存在,则创建文件 |
‘x’ | 以只写方式打开,只能写文件 | 如果文件存在,则抛出异常FileExistsError 如果文件不存在,则创建文件 |
‘+’ | 以读写方式打开,可以读写文件 | 不能单独使用,只能添加到其他打开方式的后面 ‘r+’:参见’r’的备注 ‘w+’:参见’w’的备注 ‘a+’:参见’a’的备注 ‘x+’:参见’x’的备注 |
‘t’ | 以文本方式打开 | 文件默认打开方式,不能单独使用,只能添加到其他打开方式的后面: ‘rt’,’wt’,’at’,’rt+’,’wt+’,’at+’,’xt+’ |
‘b’ | 以二进制方式打开 | 例如:打开图片不能单独使用,只能添加到其他打开方式的后面: ‘rb’,’wb’,’ab’,’xb’,’rb+’,’wb+’,’ab+’,’xb+’ |
读文件
可以调用内置函数open()
并以只读方式或读写方式打开文件。返回的文件对象有三个用于读文件的方法:
1、read([size]),如果不关闭文件,每次调用此方法,将从上一次调用此方法的地方继续读取文件。
- 如果不传参数,读到文件尾部。
- 如果传入参数size,用于指定字节数,
当指定的字节数小于读到文件尾的字节数时,读取指定的字节数;
当指定的字节数大于读到文件尾的字节数时,或当指定的字节数小于0时,读取到文件尾部;
>>> fh = open('a.txt', 'r')
>>> fh.read()
'1234567890\nqwertyuiop\nasdfghjkl\nzxcvbnm\n'
>>> fh.read() # 由于已经读到了文件尾部且没有关闭文件,再次调用将从尾部读取,没有读取到数据
''
>>> fh.close()
>>> fh = open('a.txt', 'r')
>>> fh.read(-2) # 传入负数,将直接读取到文件尾部
'1234567890\nqwertyuiop\nasdfghjkl\nzxcvbnm\n'
>>> fh.close()
注意:如果文件较大,使用read()读取全部文件会导致内存占用较大,因此,最好多次调用read([size]),指定的size不要超过默认缓冲区的大小,否则,可能并不能读取到指定的字节数。
默认缓冲区大小通过标准库中io模块的DEFAULT_BUFFER_SIZE获取
>>> import io
>>> io.DEFAULT_BUFFER_SIZE
8192
2、readline([size]),如果不关闭文件,每次调用此方法,将从上一次调用此方法的地方继续读取文件。
- 如果不传参数,读到行尾。
- 如果传入参数size,用于指定字节数,
当指定的字节数小于读到行尾的字节数时,读取指定的字节数;
当指定的字节数大于读到行尾的字节数时,或当指定的字节数小于0时,读取到行尾部;
总之,最多读到行尾。
# 如果不传参数,读到行尾
>>> fh = open('a.txt', 'r')
>>> fh.readline()
'1234567890\n'
>>> fh.readline()
'qwertyuiop\n'
>>> fh.readline()
'asdfghjkl\n'
>>> fh.readline()
'zxcvbnm\n'
>>> fh.readline()
''
>>> fh.close()
# 当指定的字节数小于读到行尾的字节数时,读取指定的字节数
>>> fh = open('a.txt', 'r')
>>> fh.readline(7)
'1234567'
>>> fh.readline(7) # 当指定的字节数大于读到行尾的字节数时,或当指定的字节数小于0时,读取到行尾部
'890\n'
>>> fh.readline(7)
'qwertyu'
>>> fh.readline(7)
'iop\n'
>>> fh.readline(7)
'asdfghj'
>>> fh.readline(7)
'kl\n'
>>> fh.readline(7)
'zxcvbnm'
>>> fh.readline(7)
'\n'
>>> fh.readline(7)
''
>>> fh.close()
# 当指定的字节数大于读到行尾的字节数时,或当指定的字节数小于0时,读取到行尾部
>>> fh.close()
>>> fh = open('a.txt', 'r')
>>> fh.readline(20)
'1234567890\n'
>>> fh.readline(20)
'qwertyuiop\n'
>>> fh.readline(20)
'asdfghjkl\n'
>>> fh.readline(20)
'zxcvbnm\n'
>>> fh.readline(20)
''
>>> fh.close()
3、readlines([size])
- 如果不传参数,读到文件尾部,返回每一行组成的列表。
- 如果传入参数,size用于指定字节数,
当指定的字节数小于读到文件尾的字节数时,一直读取到最后一个字符所在的行尾;
当指定的字节数大于读到文件尾的字节数时,或当指定的字节数小于0时,读取到文件尾部;
# 如果不传参数,读到文件尾部,返回每一行组成的列表
>>> fh = open('a.txt', 'r')
>>> fh.readlines()
['1234567890\n', 'qwertyuiop\n', 'asdfghjkl\n', 'zxcvbnm\n']
>>>
>>> fh.readlines()
[]
>>> fh.close()
# 当指定的字节数小于读到文件尾的字节数时,一直读取到最后一个字符所在的行尾
>>> fh = open('a.txt', 'r')
>>>
>>> fh.readlines(5)
['1234567890\n']
>>> fh.readlines(5)
['qwertyuiop\n']
>>> fh.readlines(5)
['asdfghjkl\n']
>>> fh.readlines(5)
['zxcvbnm\n']
>>> fh.readlines(5)
[]
>>> fh.close()
# 当指定的字节数大于读到文件尾的字节数时,或当指定的字节数小于0时,读取到文件尾部
>>> fh = open('a.txt', 'r')
>>> fh.readlines(-5)
['1234567890\n', 'qwertyuiop\n', 'asdfghjkl\n', 'zxcvbnm\n']
>>> fh.close()
写文件
写文件之前,必须打开文件。
可以调用内置函数open()
并且以只写方式、追加方式、读写方式打开文件。这样,返回的文件对象有两个用于写文件的方法:
1、write(text)
- 用于将指定的字符串写入到文件中。方法的返回值是写入的字符数,即指定的字符串的长度。
>>> fh = open('a.txt', 'w')
>>> fh.write('hello')
5
>>> fh.write(' python')
7
>>> fh.close()
>>>
2、writelines(seq)
- 用于将指定的字符串序列写入到文件中
>>> fh = open('a.txt', 'w')
>>> fh.writelines(['qwe\n', 'asd\n', 'zxc\n'])
>>> fh.close()
调用这个两个方法后,会将指定的字符串写入到缓存中,手动调用方法flush()
或者close()
,或者当写入的数据量大于等于缓存的容量时,缓存中的字符串才会被写入文件中
关闭文件
文件在使用完毕后必须要关闭,这是因为文件对象会占用操作系统的资源,并且操作系统在某一时刻所能打开的文件数量也是有限的。
读文件或写文件时都有可能发生异常,从而导致方法close()
不会被调用,为了保证方法close()
总能被调用,可以把读文件或写文件的操作放在try
语句块中,把方法close()
的调用放在finally
中,
伪代码如下:
try:
读文件或写文件
finally:
调用方法close()关闭文件
由于文件对象实现了特殊方法__enter__()
和__exit__()
,所以文件对象可以作为上下文管理器。其中特殊方法__enter__()
用于返回打开的文件对象,特殊方法__exit__()
中关闭打开的文件,因此,上面的伪代码可以使用with语句实现:
with 打开文件 as file:
读写文件
文件指针
任何文件对象都有一个文件指针,用于指向文件中的某个位置。
读写文件时,是从文件指针的当前位置开始读写的,在读写过程中,文件指针会随之往后移动。
打开文件后,文件指针的位置
以追加(’a’)方式打开文件后,文件指针指向文件的结尾位置;以其他方式打开文件后,文件指针指向文件的起始位置。
调用文件对象的方法tell(),返回文件指针的当前位置。
>>> fh = open('a.txt', 'r')
>>> fh.tell()
0
>>> fh.close()
>>> fh = open('a.txt', 'a') # 追加方式文件指针在文件的末尾
>>>
>>> fh.tell()
11
>>>
>>> fh.close()
在读写文件时,文件指针移动过程
>>> fh = open('a.txt', 'r')
>>> fh.tell() # 起始位置是0
0
>>> fh.read(3)
'qwe'
>>>
>>> fh.tell()
3
>>> fh.read(5)
'\nasd\n'
>>> fh.tell()
8
>>> fh.close()
自由移动文件指针
可以调用文件对象的方法seek()
,将文件指针自由移动到参数指定的位置
语法格式:
seek(offset, [whence])
参数offset表示偏移量,可以为正数和负数,正数表示往后偏移,负数表示往前偏移。
参数whence是可选的,表示相对偏移位置,有三种取值:
1、os.SEEK_SET:相对文件的起始位置,值为0,默认值
2、os.SEEK_CUR:相对文件的当前位置,值为1
3、os.SEEK_END:相对文件的结尾位置,值为2
只有以二进制方式打开的文件,才能支持上述三种方式,如果以文本方式打开的文件,只支持相对文件的起始位置。
如果要使用os.SEEK_SET、os.SEEK_CUR、os.SEEK_END,需要导入os模块,但是这三个属性其实就是相当于数值0、1、2
os.SEEK_SET == 0
os.SEEK_CUR == 1
os.SEEK_END == 2
>>> fh = open('a.txt', 'r') # 因为是以文本方式打开的,因此只支持相对文件的起始位置
>>> fh.tell()
0
>>> fh.seek(5) # 从文件的起始位置,偏移5个指针
5
>>> fh.tell()
5
>>> fh.read(2)
'56'
>>>
>>> fh.seek(0)
0
>>>
>>> fh.tell() # 从文件的起始位置,偏移0个指针,回到文件的起始位置
0
>>> fh.read(2)
'01'
>>> fh.seek(-5, 2) # 因为是以文本方式打开的,因此只支持相对文件的起始位置,另外两种方式就会抛出异常
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
io.UnsupportedOperation: can't do nonzero end-relative seeks
>>> fh = open('a.txt', 'rb')
>>> fh.tell()
0
>>> fh.seek(-2, 2)
20
>>> fh.tell()
20
>>>
>>> fh.read()
b'j\n'
>>> fh.close()
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 289211569@qq.com