使用python拆分大文件

时间:2011-11-11 15:58:50

标签: python split

我在尝试拆分大文件(比如大约10GB)时遇到了一些麻烦。基本思路是简单地读取行,并将每行分组,将40000行写入一个文件。 但是有两种方式可以阅读"文件。

1)第一个是立即读取WHOLE文件,并将其变为LIST。但是这需要将WHOLE文件加载到内存中,这对于太大的文件来说是痛苦的。 (我想我之前问过这样的问题) 在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] or list[80000,120000] 或者使用列表的优点是我们可以轻松指向特定的行。

2)第二种方式是逐行阅读;在阅读时处理该行。那些读取行不会被保存在内存中。 例子包括:

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

for line in fileinput.FileInput(fileName):

我确定gzip.open,这个f不是列表,而是文件对象。似乎我们只能逐行处理;然后我怎么能执行这个" split"工作?如何指向文件对象的特定行?

由于

6 个答案:

答案 0 :(得分:15)

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()

答案 1 :(得分:4)

如果在每个文件中都有特定数量的文件行没有什么特别之处,readlines() function也接受一个大小'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 

答案 2 :(得分:3)

chunk_size = 40000
fout = None
for (i, line) in enumerate(fileinput.FileInput(filename)):
    if i % chunk_size == 0:
        if fout: fout.close()
        fout = open('output%d.txt' % (i/chunk_size), 'w')
    fout.write(line)
fout.close()

答案 3 :(得分:2)

对于10GB文件,第二种方法显然是要走的路。以下是您需要做的概述:

  1. 打开输入文件。
  2. 打开第一个输出文件。
  3. 从输入文件中读取一行并将其写入输出文件。
  4. 保持计数到当前输出文件的行数;一旦达到40000,关闭输出文件,然后打开下一个文件。
  5. 重复步骤3-4,直到您到达输入文件的末尾。
  6. 关闭这两个文件。

答案 4 :(得分:0)

显然,当您正在处理文件时,您需要以某种方式迭代文件的内容 - 无论您是手动执行还是让Python API的一部分为您执行(例如readlines) ()方法)并不重要。在大O分析中,这意味着您将花费O(n)时间(n是文件的大小)。

但是将文件读入内存也需要O(n)空间。虽然有时我们确实需要将10 GB的文件读入内存,但您的特定问题并不需要这样。我们可以直接迭代文件对象。当然,文件对象确实需要空间,但我们没有理由以两种不同的形式保存文件的内容两次。

因此,我会选择你的第二个解决方案。

答案 5 :(得分:0)

我发现的最佳解决方案是使用库文件拆分 (https://pypi.org/project/filesplit/)。
您只需要指定输入文件、输出文件夹和输出文件所需的字节大小。最后,图书馆将为您完成所有工作。

from fsplit.filesplit import Filesplit
fs = Filesplit()
def split_cb(f, s):
    print("file: {0}, size: {1}".format(f, s))

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