我有一个大的xml文件(40 Gb),我需要拆分成更小的块。我正在使用有限的空间,所以当我将它们写入新文件时,有没有办法从原始文件中删除行?
谢谢!
答案 0 :(得分:7)
假设您要将文件拆分为N个片段,然后只需从文件背面开始阅读(或多或少)并反复拨打truncate:
截断文件的大小。如果存在可选的大小参数,则文件将截断为(最多)该大小。大小默认为当前位置。当前文件位置未更改。 ...
import os
import stat
BUF_SIZE = 4096
size = os.stat("large_file")[stat.ST_SIZE]
chunk_size = size // N
# or simply set a fixed chunk size based on your free disk space
c = 0
in_ = open("large_file", "r+")
while size > 0:
in_.seek(-min(size, chunk_size), 2)
# now you have to find a safe place to split the file at somehow
# just read forward until you found one
...
old_pos = in_.tell()
with open("small_chunk%2d" % (c, ), "w") as out:
b = in_.read(BUF_SIZE)
while len(b) > 0:
out.write(b)
b = in_.read(BUF_SIZE)
in_.truncate(old_pos)
size = old_pos
c += 1
小心,因为我没有测试任何这个。截断调用后可能需要调用flush
,我不知道文件系统实际释放空间的速度有多快。
答案 1 :(得分:2)
如果您使用的是Linux / Unix,为什么不使用this guy之类的split命令呢?
split --bytes=100m /input/file /output/dir/prefix
编辑:然后使用csplit。
答案 2 :(得分:1)
我很确定有,因为我甚至可以编辑/读取我运行的脚本的源文件,但最大的问题可能是如果你开始的话会做的所有转移在文件的开头。另一方面,如果您浏览文件并记录行的所有起始位置,则可以按相反的位置顺序复制行;一旦完成,您可以返回,一次一个地获取新文件,并且(如果它们足够小),使用readlines()生成列表,颠倒列表的顺序,然后寻找开头然后用新的行覆盖旧文件中的行。
(在使用truncate()
方法从末尾读取第一个行后,你会截断文件,如果在没有任何参数的情况下使用,除了文件对象之外,它会截断当前文件位置之外的所有数据,假设您正在使用其中一个类或io
包中某个类的子类来读取您的文件。您只需要确保当前文件位置在结束时开始。要写入新文件的最后一行。)
编辑:根据您对必须在正确的结束标记处进行分色的注释,您可能还需要开发一种算法来检测此类标记(可能使用peek
方法),可能使用正则表达式。
答案 3 :(得分:0)
如果时间不是主要因素(或磁盘驱动器磨损):
如果Python没有为您提供这种级别的控制,您可能需要深入了解C.
答案 4 :(得分:0)
你总是可以解析XML文件并写出来说每个10000个元素都有自己的文件。请查看此链接的“增量分析”部分。 http://effbot.org/zone/element-iterparse.htm
答案 5 :(得分:0)
这是我的剧本......
import string
import os
from ftplib import FTP
# make ftp connection
ftp = FTP('server')
ftp.login('user', 'pwd')
ftp.cwd('/dir')
f1 = open('large_file.xml', 'r')
size = 0
split = False
count = 0
for line in f1:
if not split:
file = 'split_'+str(count)+'.xml'
f2 = open(file, 'w')
if count > 0:
f2.write('<?xml version="1.0"?>\n')
f2.write('<StartTag xmlns="http://www.blah/1.2.0">\n')
size = 0
count += 1
split = True
if size < 1073741824:
f2.write(line)
size += len(line)
elif str(line) == '</EndTag>\n':
f2.write(line)
f2.write('</EndEndTag>\n')
print('completed file %s' %str(count))
f2.close()
f2 = open(file, 'r')
print("ftp'ing file...")
ftp.storbinary('STOR ' + file, f2)
print('ftp done.')
split = False
f2.close()
os.remove(file)
else:
f2.write(line)
size += len(line)
答案 6 :(得分:-1)
是购买新硬盘的时候了!
您可以在尝试所有其他答案之前进行备份,并且不会丢失数据:)