2009-07-17 45 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)