python 文件读写小结以及如何读取大文件

1. 读文件

打开一个文件用 open() 方法(open()返回一个文件对象,它是可迭代的):

f = open('test.txt',  'r')  # r表示是文本文件,rb是二进制文件(这个mode参数默认值就是r)
f.close()  # 文件使用完毕后必须关闭,因为文件对象会占用操作系统的资源,并且操作系统同一时间能打开的文件数量也是有限的

# 但是每次都这么写实在太繁琐,所以,Python引入了with语句来自动帮我们调用close()方法:
with open('/path/to/file', 'r') as f:
    print(f.read())

  python 文件对象提供了三个“读”方法: read()readline()readlines()。每种方法可以接受一个变量以限制每次读取的数据量。
注意:这三种方法是把每行末尾的 \n 也读进来了,它并不会默认的把'\n'去掉,需要我们手动去掉。

  • read() 每次读取整个文件,它通常用于将文件内容放到一个字符串变量中。如果文件大于可用内存,为了保险起见,可以反复调用read(size)方法,每次最多读取size个字节的内容。
  • readlines() 之间的差异是后者一次读取整个文件,象 .read() 一样。.readlines() 自动将文件内容分析成一个行的列表。
  • readline() 每次只读取一行,通常比readlines() 慢得多。仅当没有足够内存可以一次读取整个文件时,才应该使用 readline()。

2. 写文件

f = open('test.txt', 'w') # 若是'wb'就表示写二进制文件
f.write('Hello, world!')
f.close()

注意: w 这个模式是这样:如果没有这个文件,就创建一个;如果有,那么就会先把原文件的内容清空再写入新的东西。所以若不想清空原来的内容而是直接在后面追加新的内容,就用 a 这个模式。
  我们可以反复调用 write() 来写入文件,但是务必要调用 f.close() 来关闭文件。当我们写文件时,操作系统往往不会立刻把数据写入磁盘,而是放到内存缓存起来,空闲的时候再慢慢写入。只有调用 close() 方法时,操作系统才保证把没有写入的数据全部写入磁盘。忘记调用 close() 的后果是数据可能只写了一部分到磁盘,剩下的丢失了。所以,还是用 with 语句来得保险:

with open('test.txt', 'w') as f:
    f.write('Hello, world!')

python文件对象提供了两个“写”方法: write()writelines()

  • write()方法和read()、readline()方法对应,是将字符串写入到文件中。
  • writelines()方法和readlines()方法对应,也是针对列表的操作。它接收一个字符串列表作为参数,将他们写入到文件中,换行符不会自动的加入,因此需要显式的加入换行符。

3. 关于open()的mode参数:

  • r:读
  • w:写
  • a:追加
  • r+ == r+w(可读可写,文件若不存在就报错(IOError))
  • w+ == w+r(可读可写,文件若不存在就创建)
  • a+ == a+r(可追加可写,文件若不存在就创建)
  • 对应的,如果是二进制文件,就都加一个b就好啦:
    rb  wb  ab  rb+  wb+  ab+

4. 字符编码

要读取非UTF-8编码的文本文件,需要给open()函数传入encoding参数,例如,读取GBK编码的文件:

f = open('test.txt', 'r', encoding='gbk')
f.read()

遇到有些编码不规范的文件,你可能会遇到UnicodeDecodeError,因为在文本文件中可能夹杂了一些非法编码的字符。遇到这种情况,open()函数还接收一个errors参数,表示如果遇到编码错误后如何处理。最简单的方式是直接忽略:

f = open('test.txt', 'r', encoding='gbk', errors='ignore')
5. 读取大文件

  最近处理文本文档时(文件约 28GB 大小),出现memoryError错误和文件读取太慢的问题,处理大文件是很容易想到的就是将大文件分割成若干小文件处理,处理完每个小文件后释放该部分内存。这里用了 iter & yield

5.1 Read In Chunks
def read_in_chunks(filePath, chunk_size=1024*1024):
    """
    Lazy function (generator) to read a file piece by piece.    
    Default chunk size: 1M    
    You can set your own chunk size     
    """    
    try:
        file_object = open(filePath)    
        while True:
            chunk_data = file_object.read(chunk_size)        
            if not chunk_data:            
                break        
            yield chunk_data
    finally:
        if file_object:
            f.close()
        
if __name__ == "__main__":    
    filePath = './path/filename'    
    for chunk in read_in_chunks(filePath):        
        process(chunk) # <do something with chunk>
5.2 Using with open()

对可迭代对象 f,进行迭代遍历:for line in f,会自动地使用缓冲IO(buffered IO)以及内存管理,而不必担心任何大文件的问题。

with open(filename, 'rb') as f:
    for line in f:
        <do something with the line>
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 今天感触:我老妈出去避暑,由于考虑到娃儿暑假在家,老爸就留在重庆没去,我每天又早出晚归,这几天全是七十几岁的老爸在...
    晓茂阅读 1,521评论 2 4
  • Don't ask whether the world is good or evil, ...
    镜里无涯心有涯阅读 1,826评论 0 0
  • 时隔二十多年,我居然又拿起了课本,背诵起课文来。 现在背的是新概念二,一课大概​150个单词,念一遍一分钟的样子。...
    Jeff_孙阅读 3,795评论 0 0
  • 男友喜欢披肩发或者披肩发看起来更有女人味又或者披肩发可以显脸小等等。女生留长发的目的可能有很多。 单就女生在夏天留...
    东南萌阅读 4,746评论 8 1