读写文件前,我们先必须了解一下,在磁盘上读写文件的功能都是由操作系统提供的,现代操作系统不允许普通的程序直接操作磁盘,所以,读写文件就是请求操作系统打开一个文件对象(通常称为文件描述符),然后,通过操作系统提供的接口从这个文件对象中读取数据(读文件),或者把数据写入这个文件对象(写文件)。
python open() 函数用于打开一个文件,创建一个 file 对象,相关的方法才可以调用它进行读写。
open(name[, mode[, buffering]])
- name : 字符串,文件名。
- mode : 打开文件的模式:只读,写入,追加等。所有可取值见如下的完全列表。这个参数是非强制的,默认文件访问模式为只读(r)。
- buffering : 如果 buffering 的值被设为 0,就不会有寄存。如果 buffering 的值取 1,访问文件时会寄存行。如果将 buffering 的值设为大于 1 的整数,表明了这就是的寄存区的缓冲大小。如果取负值,寄存区的缓冲大小则为系统默认。
不同模式打开文件的完全列表:
模式
|
描述
|
r
|
以只读方式打开文件。文件的指针将会放在文件的开头。这是默认模式。
|
rb
|
以二进制格式打开一个文件用于只读。文件指针将会放在文件的开头。这是默认模式。
|
r+
|
打开一个文件用于读写。文件指针将会放在文件的开头。
|
rb+
|
以二进制格式打开一个文件用于读写。文件指针将会放在文件的开头。
|
w
|
打开一个文件只用于写入。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。
|
wb
|
以二进制格式打开一个文件只用于写入。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。
|
w+
|
打开一个文件用于读写。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。
|
wb+
|
以二进制格式打开一个文件用于读写。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。
|
a
|
打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。
|
ab
|
以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。
|
a+
|
打开一个文件用于读写。如果该文件已存在,文件指针将会放在文件的结尾。文件打开时会是追加模式。如果该文件不存在,创建新文件用于读写。
|
ab+
|
以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。如果该文件不存在,创建新文件用于读写。
|
file 对象方法
- file.read([size]):size 未指定则返回整个文件,如果文件大小 >2 倍内存则有问题,f.read()读到文件尾时返回""(空字串)。
- file.readline():返回一行。
- file.readlines([size]) :返回包含size行的列表, size 未指定则返回全部行。
- for line in f: print line :通过迭代器访问。
- f.write("hello "):如果要写入字符串以外的数据,先将他转换为字符串。
- f.tell():返回一个整数,表示当前文件指针的位置(就是到文件头的比特数)。
- f.seek(偏移量,[起始位置]):用来移动文件指针。
- 偏移量: 单位为比特,可正可负
- 起始位置: 0 - 文件头, 默认值; 1 - 当前位置; 2 - 文件尾
- f.close() 关闭文件
读文件
以读文件的模式打开一个文件对象
>>> f = open('~/test.txt', 'r')
|
如果文件不存在,open()函数就会抛出一个IOError的错误,并且给出错误码和详细的信息告诉你文件不存在:
>>> f=open('~/notfound.txt', 'r')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
FileNotFoundError: [Errno 2] No such file or directory: '~/notfound.txt'
|
如果文件打开成功,接下来,调用read()方法可以一次读取文件的全部内容,Python把内容读到内存,用一个str对象表示:
|
>>> f.read()
'Hello, world!'
|
最后一步是调用close()方法关闭文件。文件使用完毕后必须关闭,因为文件对象会占用操作系统的资源,并且操作系统同一时间能打开的文件数量也是有限的
|
>>> f.close()
|
由于文件读写时都有可能产生IOError,一旦出错,后面的f.close()就不会调用。所以,为了保证无论是否出错都能正确地关闭文件,我们可以使用try ... finally来实现:
|
try:
f = open('/path/to/file', 'r')
print(f.read())
finally:
if f:
f.close()
|
但是每次都这么写实在太繁琐,所以,Python引入了with语句来自动帮我们调用close()方法:
|
with open('/path/to/file', 'r') as f:
print(f.read())
这和前面的try ... finally是一样的,但是代码更佳简洁,并且不必调用f.close()方法。
|
对于多文件的读写
|
|
调用read()会一次性读取文件的全部内容,如果文件有10G,内存就爆了,所以,要保险起见,可以反复调用read(size)方法,每次最多读取size个字节的内容。另外,调用readline()可以每次读取一行内容,调用readlines()一次读取所有内容并按行返回list。因此,要根据需要决定怎么调用。
如果文件很小,read()一次性读取最方便;如果不能确定文件大小,反复调用read(size)比较保险;如果是配置文件,调用readlines()最方便
for line in f.readlines():
print(line.strip()) # 把末尾的'
'删掉
python中read() readline() 以及readlines()的对比
.read() 每次读取整个文件,它通常用于将文件内容放到一个字符串变量中。当文件大于可用内存时,不能用read()进行处理。
.readlines() 一次读取整个文件,自动将文件内容分析成一个行的列表,该列表可以由 Python 的 for ... in ... 结构进行处理。
.readline() 每次只读取一行,比readlines() 慢得多。仅当没有足够内存可以一次性读取整个文件时,才应该使用 .readline()。
|
统计文件行数
如果要统计文件的行数,可以这样写:
count = len(open(filepath, 'r').readlines())
这种方法简单,但是可能比较慢,当文件比较大时甚至不能工作。
可以利用enumerate():
count = 0 for index, line in enumerate(open(filepath,'r')): count += 1
参考:https://blog.csdn.net/churximi/java/article/details/51648388
写文件
写文件和读文件是一样的,唯一区别是调用open()函数时,传入标识符'w'或者'wb'表示写文本文件或写二进制文件
|
>>> f = open('/Users/michael/test.txt', 'w')
>>> f.write('Hello, world!')
>>> f.close()
你可以反复调用write()来写入文件,但是务必要调用f.close()来关闭文件。当我们写文件时,操作系统往往不会立刻把数据写入磁盘,而是放到内存缓存起来,空闲的时候再慢慢写入。
|
只有调用close()方法时,操作系统才保证把没有写入的数据全部写入磁盘。
忘记调用close()的后果是数据可能只写了一部分到磁盘,剩下的丢失了。
|
使用with语句比较保险
|
with open('/Users/michael/test.txt', 'w') as f:
f.write('Hello, world!')
|
|
要写入特定编码的文本文件,需要给open()函数传入encoding参数,将字符串自动转换成指定编码
|
例如,读取GBK编码的文件:
>>> f = open('/Users/michael/gbk.txt', 'r', encoding='gbk')
>>> f.read()
'测试'
|
遇到有些编码不规范的文件,你可能会遇到UnicodeDecodeError,因为在文本文件中可能夹杂了一些非法编码的字符。遇到这种情况,open()函数还接收一个errors参数,表示如果遇到编码错误后如何处理。最简单的方式是直接忽略:
>>> f = open('/Users/michael/gbk.txt', 'r', encoding='gbk', errors='ignore')
|
读取二进制文件,比如图片、视频等等,用'rb'模式打开文件即可
|
>>> f = open('/Users/michael/test.jpg', 'rb')
>>> f.read()
b'xffxd8xffxe1x00x18Exifx00x00...' # 十六进制表示的字节
|
|
多个文件的读写,可以写成以下两种方式
|
with open('~/output_measures.txt','r') as f:
with open('~/output_measures2.txt','r') as f1:
with open('~/output_output_bk.txt','r') as f2:
........
|
with open('~/output_measures.txt','r') as f:
........
with open('~/output_measures2.txt','r') as f1:
........
with open('~/output_output_bk.txt','r') as f2:
........
|
总结:以后读写文件都使用with open语句,不要再像以前那样用f = open()这种语句了