2012-12-21 44 views
3

我試圖將PHP代碼轉換爲Python,並且我在替換行時遇到了問題。儘管我發現使用Python更容易,但我完全迷失了;我可以找到要替換的行,我可以在行尾添加一些內容,但是我無法再在該文件上再寫一行。在Python上替換一行

file = open("cache.ucb", 'rb') 
for line in file: 
    if line.split('~!')[0] == ex[4]: 
     line += "~!" + mask[0] 
     line = line.rstrip() + "\n" 
     # Write on the file here! 

基本上,file使用~!作爲隔板,並且我讀每一行。如果第一個令牌與該行的~!分隔開始於ex[4](可能是Catbuntu),我想在該行的末尾附加mask[0],該位置可能爲Bousie。然後我刪除新的行字符並添加一個到最後。

還有問題。我想按原樣寫入文件,但只更改該行。那可能嗎?

+3

請仔細閱讀[二進制數據的讀寫](http://mail.python.org/pipermail/tutor/2000-July/001883.html)。 – Droogans

+0

正如Droogans提到的,除非你有一些明確的理由以二進制形式讀取數據,否則最好省略open()調用的標誌。 – Drakekin

回答

5

假設你在蟒蛇> = 2.7,下面應該工作請客

original = open(filename) 
newfile = [] 
for line in original: 
    if line.split('~!')[0] == ex[4]: 
     line += "~!" + mask[0] 
     line = line.rstrip() + "\n" 
    newfile.append(line) 
original.close() 
amended.open(filename, "w") 
amended.writeLines(newfile) 
amended.close() 

如果你對Python的2.6或更低不管是什麼原因,與更換倒數第二行:

amended.write("".join(newfile)) 

編輯:修復,以取代從問題中複製的錯誤,將文件名分解出來。

+0

謝謝!它工作,但我不得不修改一些東西。我編輯了答案......謝謝! –

+0

我假設你想要'在文件行:',而不是'在線作爲文件:'在這裏。 (任擇議定書的問題有同樣的問題。) – abarnert

+0

是的,應該vertabrim複製之前已經檢查過的OP代碼。 – Drakekin

0

您沒有打開文件供您撰寫。

file = open("cache.ucb", 'rb') 

該行以二進制模式打開文件進行讀取。您還需要打開它才能寫入。

嘗試在寫入模式下打開文件'w'並寫回行。

或者你可以簡單地打開你的讀/寫文件在開始和你的循環裏面寫:

file = open("cache.ucb", 'a+') 
+0

他試圖「按照原樣寫入文件,但只更改該行」 - 並且不保留該行的長度。你不能那樣做。 – abarnert

1

在開放模式「WB」的文件,並把file.write(line)在你的循環結束。

2

您不能就地修改文件,至少在您想要將字符插入一行時不行。你最終會覆蓋下一行的開始。

有兩種不同的方式來做到這一點:

  1. 文件讀入到內存,關閉它,然後寫回的新版本。
  2. 隨時寫入新的臨時文件,然後將其移至原始版本上。

那麼,你如何選擇它們呢?我會試着總結的差異,責令使每一個通常勝過下面,如果它是重要的那些(不過這只是「一般」 - 你必須想通過自己的用例):

  • 2沒有按要求把整個事情都放在記憶裏。如果你的文件長20GB,這顯然是一個巨大的勝利;如果是16KB,那沒關係。

  • 2使整個操作成爲原子。即使中途失敗,或者某個其他進程在您更改文件的過程中嘗試讀取文件,任何人都無法看到一些無效的半修改文件;他們會看到原始文件或新文件。

  • 2需要一些可用磁盤空間(因爲臨時存在兩個文件副本)。

  • 2如果你關心Windows和POSIX,那麼頸部疼痛很大。

  • 2如果原始文件和臨時目錄位於不同的文件系統上,則可能涉及到跨文件系統的複製,除非您小心。

  • 2更簡單,如果上述兩個都不是問題。

德拉克金的回答告訴你如何做#1。

這裏是如何做到#2,如果你不關心Windows或有關跨文件系統的問題:

infile = open("cache.ucb", 'rb') 
outfile = tempfile.NamedTemporaryFile(delete=False) 
for line in infile: 
    if line.split('~!')[0] == ex[4]: 
     line += "~!" + mask[0] 
     line = line.rstrip() + "\n" 
    outfile.write(line) 
infile.close() 
os.rename(outfile.name, "cache.ucb") 
outfile.close() 

你可以解決,例如,通過dir=os.path.dirname(original path)NamedTemporaryFile構造跨文件系統問題,但前提是您確定您始終有權在原始文件旁邊創建新文件(但並不總能保證,因爲您有權重寫原始UNIX權限,Windows ACL,OS X沙盒等等都給出了可能是錯誤的方法)。

爲了解決Windows的問題......好吧,從Is an atomic file rename (with overwrite) possible on Windows開始,以及類似的討論遍及互聯網。

+2

出了人的興趣,就是在內存中,或在實踐中的臨時文件持有新版本有什麼區別? – Drakekin

+1

@Drakekin:我會更新的答案,而不是試圖在註釋回答。 – abarnert

+0

感謝您抽出寶貴的時間來解釋它。 – Drakekin