Python初学者。最近用Python处理文本文件,小的文件大概有400M+,大的文件有4G+,基本目标是按照一些特定的关键词把这些大文件整理并分割成一些小文件。
最开始的想法是使用生成器generator,按行读取文件,每检查到一个分割关键词,就将之前读取的行组成字符串并返回。可以看出,这种做法涉及多次字符串的复制拼接,即便是用上了.join()的操作,也会大量占用内存,计算效率也较为低下。
其实,假如每读取一行,就直接写入分割出来的小文件中,检查到一个分割关键词之后就关闭文件并打开新的文件用于下一轮的写入。这样的效率应该会高很多。但这种简单的方式需要增加较为冗余的条件判断语句,让我觉得并不优雅。
我希望能够把“写入单个分割文件”抽象成一个以大文件为参量的函数,每执行一次这个函数,就能分割出一个小文件来。但是我担心,是否每次调用这样一个函数,都是从文件开头重新扫描,而不是从上次检查到分割关键词并退出的地方开始?这也就是我最初使用generator的动机,因为在执行一个generator函数后,下一次重新调用时,可以从上次执行退出的地点继续运行。
然而后来我发现是自己太愚蠢了,因为在python里面,文件迭代器的属性可以很好地帮助我完成generator所完成的功能:
假如有一个foo.txt文件,它的文件内容是这样:
line1
line2
line3
line4
line5
line6
line7
line8
line9
# coding = gbk
# program name: FileIterator
import os
import sys
os.chdir(sys.path[0])
def iterateFile(File):
i = 1
for line in File:
print 'iteration1 line%s is:'%i, line,
i += 1
if i == 5:
break
with open('foo.txt','r') as TestFile:
iterateFile(TestFile)
iterateFile(TestFile)
with open('foo.txt','r') as TestFile:
iterateFile(TestFile)
TestFile.seek(0)
iterateFile(TestFile)
可以看出,第一次打开TestFile时,在第二次函数调用的时候,文件的读取并非是从TestFile的第一行重新开始,而是从上一次函数退出的地方继续读取。这主要是因为for循环的退出不会影响TestFile这个文件对象内秉的__next__属性,除非这个文件对象被重置;而在第二次打开TestFile时,由于添加了seek(0)语句,使得文件迭代器被重置。