Python 如何加载一个大文件并将其剪切成更小的文件?
我有一个大约4MB的文件(我称之为大文件)…这个文件大约有160000行…在一个特定的格式中…我需要以固定的间隔(而不是相等的间隔)剪切它们,即在某个格式的末尾,然后将部分写入另一个文件中 基本上,我想要的是将大文件的信息复制到许多较小的文件中…当我读取大文件时,继续将信息写入一个文件中,在某个模式发生后,然后结束此操作并开始将该行写入另一个文件中 通常情况下,如果是一个小文件,我想它可以完成。不知道我是否可以执行file.readline()读取每行检查模式是否结束,然后将其写入一个文件如果模式结束,然后更改文件名打开新文件..依此类推,但如何为这个大文件执行此操作 提前谢谢Python 如何加载一个大文件并将其剪切成更小的文件?,python,file,Python,File,我有一个大约4MB的文件(我称之为大文件)…这个文件大约有160000行…在一个特定的格式中…我需要以固定的间隔(而不是相等的间隔)剪切它们,即在某个格式的末尾,然后将部分写入另一个文件中 基本上,我想要的是将大文件的信息复制到许多较小的文件中…当我读取大文件时,继续将信息写入一个文件中,在某个模式发生后,然后结束此操作并开始将该行写入另一个文件中 通常情况下,如果是一个小文件,我想它可以完成。不知道我是否可以执行file.readline()读取每行检查模式是否结束,然后将其写入一个文件如果模
我没有提到文件格式,因为我觉得没有必要。如果需要的话,我会提到。我不打算讨论实际的代码,但是伪代码可以做到这一点
BIGFILE="filename"
SMALLFILE="smallfile1"
while(readline(bigfile)) {
write(SMALLFILE, line)
if(line matches pattern) {
SMALLFILE="smallfile++"
}
}
这是非常糟糕的代码,但也许你明白了。我还应该说,你的文件有多大并不重要,因为你无论如何都要读取文件。4MB的文件非常小,它肯定适合内存。最快的方法是全部读取,然后在每一行上迭代搜索模式,根据模式将该行写入相应的文件(您对小文件的方法)。我首先读取内存中所有所谓的大文件,作为行列表:
with open('socalledbig.txt', 'rt') as f:
lines = f.readlines()
应该只需要4MB多一点——即使按照今天的手机标准,也很小,更不用说普通电脑了
然后,执行所需的任何处理,以确定要写入较小文件的每组行的开始和结束(根据您的问题文本,我不确定这些组是否可以重叠或留下间隙,因此我提供了最通用的解决方案,在完全允许的情况下——这也将涵盖更多受约束的用例,没有实际的性能损失,尽管如果约束非常严格,代码可能会稍微简单一些)
假设您将这些数字放在列表中开始
(从要写入的第一行的0开始索引,包括在内),结束
(从第一行的0开始索引,不写入-可能合法且无害地是len(行)
或更多),名称
(您要写入的文件名),所有列表的长度当然相同
然后,最后:
assert len(starts) == len(ends) == len(names)
for s, e, n in zip(starts, ends, names):
with open(n, 'wt') as f:
f.writelines(lines[s:e])
…这就是你所需要做的
编辑:OP似乎被这些列表的概念搞糊涂了,所以让我试着给出一个例子:写入文件的每个块从包含'begin'
(包括)的行开始,并在包含'end'
的紧接着的第一行结束(也包括),并且要写入的文件的名称是result0.txt
,result1.txt
,等等。
如果“结束”的数量与“开始”的数量不同(请记住,紧随其后的第一个“结束”终止所有挂起的“开始”),则是错误的;任何行都不允许同时包含“开始”和“结束”
可以肯定,这是一组非常武断的条件,但是,OP让我们完全不知道问题的实际细节,所以除了最疯狂的猜测之外,我们还能做什么呢?-)
就是这样——关于三个长度相同的列表的断言将负责检查约束是否得到了遵守
随着约束和规范的更改,这段代码当然也会相应更改——只要它填充三个等长列表开始
,结束
,和名称
,确切地说,如何做到这一点对代码的其余部分来说一点也不重要。要编写的组中不会有重叠,但可能必须在两个组之间留出一行间隔。。你能更清楚地告诉我上面代码中的开始、结束和名字吗?@kaki,好吧,我想我已经非常清楚了,但我会添加一个完全虚假的例子(因为我们根本不知道细节)来尝试进一步帮助你——让我来编辑这个。
outfile = 0
starts = []
ends = []
names = []
for i, line in enumerate(lines):
if 'begin' in line:
if 'end' in line:
raise ValueError('Both begin and end: %r' % line)
starts.append(i)
names.append('result%d.txt' % outfile)
outfile += 1
elif 'end' in line:
ends.append(i + 1) # remember ends are EXCLUDED, hence the +1