使用python拆分大文件
我在尝试拆分大文件时遇到了一些问题(例如,大约10GB)。基本思想是简单地读取行,并将每行(比如40000行)分组到一个文件中。 但是有两种“读取”文件的方法 1) 第一种方法是一次读取整个文件,并将其列成一个列表。但这需要将整个文件加载到内存中,这对于太大的文件来说是痛苦的。(我想我以前问过这样的问题) 在python中,我尝试过的一次读取整个文件的方法包括:使用python拆分大文件,python,split,Python,Split,我在尝试拆分大文件时遇到了一些问题(例如,大约10GB)。基本思想是简单地读取行,并将每行(比如40000行)分组到一个文件中。 但是有两种“读取”文件的方法 1) 第一种方法是一次读取整个文件,并将其列成一个列表。但这需要将整个文件加载到内存中,这对于太大的文件来说是痛苦的。(我想我以前问过这样的问题) 在python中,我尝试过的一次读取整个文件的方法包括: input1=f.readlines() input1 = commands.getoutput('zcat ' + file).s
input1=f.readlines()
input1 = commands.getoutput('zcat ' + file).splitlines(True)
input1 = subprocess.Popen(["cat",file],
stdout=subprocess.PIPE,bufsize=1)
那么,我就可以通过:list[4000080000]或list[80000120000]轻松地将40000行分组到一个文件中。
或者使用列表的优点是,我们可以很容易地指向特定的行
2) 第二种方法是逐行阅读;在阅读时处理该行。那些读取的行不会保存在内存中。
例子包括:
f=gzip.open(file)
for line in f: blablabla...
或
我确信对于gzip.open,这个f不是一个列表,而是一个文件对象。似乎我们只能一行一行地处理;那么我如何执行这个“拆分”作业?如何指向文件对象的特定行
感谢提供10GB文件,第二种方法显然是可行的。以下是您需要做的事情的概要:
如果在每个文件中具有特定数量的文件行没有什么特别之处,则还接受一个大小“提示”参数,其行为如下:
# 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
如果给定一个可选参数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
显然,在处理文件时,需要以某种方式对文件内容进行迭代——不管是手动执行还是让Python API的一部分(例如readlines()方法)为您执行,都不重要。在大O分析中,这意味着您将花费O(n)时间(n是文件的大小) 但是将文件读入内存也需要O(n)空间。虽然有时我们确实需要将10 gb的文件读入内存,但您的特定问题并不需要这样做。我们可以直接迭代file对象。当然,file对象确实需要空间,但我们没有理由以两种不同的形式保存文件内容两次
因此,我将使用您的第二个解决方案。我找到的最佳解决方案是使用库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)
当你想起来的时候。。你不能。只有在阅读了前面的所有行并计算了换行次数(\n)之后,才能知道您在哪一行。(忽略特殊情况,即这是一个奇怪的文件,其中每行的长度都是已知的。)如果您希望文件中正好有40000行,我认为您应该将
I
初始化为0
,而不是1
。您需要什么软件包?@LuisFelipe不需要外部软件包,fileinput
是一个内置软件包,此功能甚至不需要它,您也可以使用普通的open()
我尝试了相同的代码,它说“name'filename'未定义”@LuisFelipefilename
是一个变量,它应该包含输入文件的路径如果num\u行%4000==0:避免在结尾处写入空文件(),除非numlines==0
您需要执行如果fout:fout.close()
退出循环后-1(1)您没有显式关闭输出文件(2)在文本模式下阅读,在二进制模式下写作,保证“如果我们在windows上的话,就可以大吃一惊”
# 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
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)