我讨厌回忆,总让人分不清自己到底是谁。

在Python2中,编码问题被人诟病不止,而写入文件与编码存在很大的关联,为此做一个总结。

使用open直接读写

f1 = open('io1.txt','a+')
f1.write('你好')
print r1.read()
f1.close()

运行结果:
ÌġXc

虽然文件写入是正常的,但是读取的时候乱码了,这是因为win系统的原因,如果想要获取正常的文字应该编码一下,print f1.read().decode(‘gbk’)就可以,但是这样很麻烦。

使用codecs读写

f=codecs.open('io2.txt','r','utf-8')
print f.encoding
# 打印文件编码格式
print f.name
# 打印文件名
for x in f.readlines():
    print x
    # 打印文件内容
f.close()

codecs可以设置编码格式,但是Python3中在open()下就可以直接设置encoding=’utf-8’,唉。

使用fileinput读写

import fileinput
with fileinput.input(files=('spam.txt', 'eggs.txt')) as f:
    for line in f:
        process(line)

主要属性

fileinput.filename()
返回当前正在处理的文件名(也就是包含了当前正在处理的文本行的文件)

fileinput.fileno()
返回当前文件的总行数。

fileinput.lineno()
返回当前的行数,这个行数是累计的。多个文件的行数会累加起来。

fileinput.filelineno()
返回当前正在处理的文件的当前行数。每次处理完一个文件并开始处理下一个文件时,该值会重置为1,重新开始计数。

fileinput.isfirstline()
当前行是当前文件的第一行时返回True,否则False

fileinput.isstdin()
当前操作对象为sys.stdin时返回True否则False。

fileinput.nextfile()
关闭当前的文件,跳到下一个文件,跳过的行不计数。

fileinput.close()
关闭整个文件链,结束迭代。

读取大文件

常规的open(xx).read(),本质上调用read()会一次性读取文件的全部内容,然后把内容保存在内存中,如果文本过大,则会导致内存溢出。

可以通过如下方法解决

使用Fileinput模块

import fileinput

for line in fileinput.input(['filename']):
    do_something(line)

调用 fileinput.input() 会按照顺序读取行,但是在读取之后不会将它们保留在内存中。

使用生成器函数

def read_in_chunks(filePath, chunk_size=1024*1024):

    file_object = open(filePath)
    while True:
        chunk_data = file_object.read(chunk_size)
        if not chunk_data:
            break
        yield chunk_data

if __name__ == "__main__":
    filePath = './path/filename.txt'
    for chunk in read_in_chunks(filePath):
        print(chunk)

使用上下文管理器

with open('filename', 'r', encoding = 'utf-8') as f:
    for line in f:
        print(line)

with 语句句柄负责打开和关闭文件(包括在内部块中引发异常时),for line in f 将文件对象 f 视为一个可迭代的数据类型,会自动使用 IO 缓存和内存管理,这样就不必担心大文件了。