2009-07-17 25 views
8

我有一个很大的xml文件(40 Gb),我需要分割成更小的块。我正在使用有限的空间,所以当我将它们写入新文件时,是否有办法从原始文件中删除行?更改python文件到位

谢谢!

+0

对不起,我不明白这是怎么回事。 – 2009-07-17 19:44:09

+1

纠正我,如果我错了,但他试图将一个非常大的文件分割成更小的部分。但是,由于该文件非常大,因此在创建分区时,他需要从原始文件中删除该部分以节省空间。 – 2009-07-17 19:47:41

+0

@Jesse - 这是正确的。 – AlbertoPL 2009-07-17 19:48:03

回答

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

我很确定这是因为我甚至可以编辑/从我运行的脚本的源文件中读取,但最大的问题可能是所有的转变,如果你从文件开始处开始。另一方面,如果您浏览文件并记录所有行的起始位置,则可以按相反的位置顺序复制行;一旦完成,你可以回去,一次一个地取出新文件,并且(如果它们足够小),使用readlines()生成一个列表,反转列表的顺序,然后寻找开始并用新的行中的行覆盖旧的顺序。假设你使用truncate()方法读取第一行数据块,如果除了文件对象之外没有任何参数使用,它将截断当前文件位置之后的所有数据,然后截取该文件,重新使用io包中的某个类或其中一个类的子类来读取文件。您只需确保当前文件位置在写入最后一行的开始处结束新文件)。

编辑:根据你的评论关于必须在适当的结束标签进行分离,你可能还必须开发一种算法来检测这些标签(可能使用peek方法),可能使用正则表达式。

2

如果你在Linux/Unix上,为什么不使用拆分命令,如this guy呢?

split --bytes=100m /input/file /output/dir/prefix 

编辑:然后使用csplit

0

如果时间不是主要因素(或磨损您的磁盘驱动器上):

  1. 打开的句柄到文件
  2. 阅读到你的分区/逻辑断点的大小(因该XML)
  3. 你的文件的其余部分保存到磁盘(不知道蟒蛇是如何处理这个就直接覆盖文件或内存使用情况)
  4. 写入分区磁盘
  5. 转到1

如果Python不给你这个级别的控制,你可能需要潜入C.

-1

它是购买新硬盘的时间!

就可以做备份尝试所有其他的答案前,没有得到数据丢失:)

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)