使用Python拆分大文件

12 投票
8 回答
34842 浏览
提问于 2025-04-17 06:07

我在处理一些大文件(比如大约10GB的文件)时遇到了一些麻烦。我的基本想法是读取文件的每一行,然后把每40000行分成一个文件。

但是,读取文件有两种方式。

1) 第一种是一次性读取整个文件,把它变成一个列表。但这样做需要把整个文件都加载到内存中,对于这么大的文件来说,这会很麻烦。(我想我之前问过类似的问题)在Python中,我尝试过的读取整个文件的方法包括:

input1=f.readlines()

input1 = commands.getoutput('zcat ' + file).splitlines(True)

input1 = subprocess.Popen(["cat",file],
                              stdout=subprocess.PIPE,bufsize=1)

这样的话,我就可以很简单地把40000行分成一个文件,比如用:list[40000,80000] 或 list[80000,120000]。使用列表的好处是我们可以很方便地指向特定的行。

2) 第二种方式是逐行读取;在读取每一行时就处理它。这样读取的行不会保存在内存中。例子包括:

f=gzip.open(file)
for line in f: blablabla...

或者

for line in fileinput.FileInput(fileName):

我知道对于gzip.open,这里的f不是一个列表,而是一个文件对象。看起来我们只能逐行处理;那么我该如何执行这个“分割”的任务呢?我该如何指向文件对象的特定行呢?

谢谢

8 个回答

4

我找到的最佳解决方案是使用一个叫做 filesplit 的库。

你只需要指定输入文件、输出文件夹和你想要的输出文件大小(以字节为单位)。最后,这个库会帮你完成所有的工作。

from fsplit.filesplit import Filesplit

def split_cb(f, s):
    print("file: {0}, size: {1}".format(f, s))

fs = Filesplit()
fs.split(file="/path/to/source/file", split_size=900000, output_dir="/pathto/output/dir", callback=split_cb)
5

如果你对每个文件的行数没有特别的要求,readlines() 函数 还可以接受一个叫做 'size hint' 的参数,它的作用是这样的:

当你给它一个可选的参数 sizehint 时,它会从文件中读取那么多字节,并且会多读一些字节以确保读取到完整的一行,然后返回这些行。这个功能通常用来高效地按行读取大文件,而不需要把整个文件都加载到内存中。返回的只会是完整的行。

...所以你可以把代码写成这样:

# assume that an average line is about 80 chars long, and that we want about 
# 40K in each file.

SIZE_HINT = 80 * 40000

fileNumber = 0
with open("inputFile.txt", "rt") as f:
   while True:
      buf = f.readlines(SIZE_HINT)
      if not buf:
         # we've read the entire file in, so we're done.
         break
      outFile = open("outFile%d.txt" % fileNumber, "wt")
      outFile.write(buf)
      outFile.close()
      fileNumber += 1 
21
NUM_OF_LINES=40000
filename = 'myinput.txt'
with open(filename) as fin:
    fout = open("output0.txt","wb")
    for i,line in enumerate(fin):
      fout.write(line)
      if (i+1)%NUM_OF_LINES == 0:
        fout.close()
        fout = open("output%d.txt"%(i/NUM_OF_LINES+1),"wb")

    fout.close()

当然可以!请把你想要翻译的内容发给我,我会帮你用简单易懂的语言解释清楚。

撰写回答