2011-10-03 80 views
9

我如何可以插入在一個文本文件中的每一行開頭的字符串的開始,我有以下代碼:插入串在每一行

f = open('./ampo.txt', 'r+') 
with open('./ampo.txt') as infile: 
    for line in infile: 
     f.insert(0, 'EDF ') 
f.close 

我得到以下錯誤:

「'文件'對象沒有屬性'插入'」

請注意,我是一個完整的編程n00b。

回答

21

Python帶有batteries included

import fileinput 
import sys 

for line in fileinput.input(['./ampo.txt'], inplace=True): 
    sys.stdout.write('EDF {l}'.format(l=line)) 

與已經發布的解決方案,這也保留了文件的權限。

+2

_「這也保留了文件權限」_我不知道。 +1 – eyquem

+0

這看起來好多了,謝謝。你能解釋一下怎麼回事? – philberndt

+4

'for-loop'一次一行地遍歷'ampo.txt'中的行。 'sys.stdout.write'和'print'幾乎相同。我之所以選擇使用'sys.stdout.write'而不是'print'是因爲'print'增加了一個額外的換行符,而'sys.stdout.write'沒有。由於'inplace = True'參數,'fileinput'將原始的ampo.txt移動到一個臨時文件,然後將stdout重定向到一個名爲'ampo.txt'的新文件。然後它複製權限並刪除臨時文件。還有更多選項,比如保留備份文件;有關更多信息,請參閱文檔。 – unutbu

7

你不能像這樣修改文件。文件不支持插入。你必須全部閱讀,然後再寫出來。

如果你願意,你可以一行一行。但在這種情況下,您需要寫入臨時文件,然後替換原始文件。因此,對於足夠小的文件,它只是簡單的做一個這樣的:

with open('./ampo.txt', 'r') as f: 
    lines = f.readlines() 
lines = ['EDF '+line for line in lines] 
with open('./ampo.txt', 'w') as f: 
    f.writelines(lines) 
+0

我建議或者懶惰的理解,或者甚至更好地添加字符串作爲讀或寫操作的一部分。這樣文件內容將只在內存中存儲一​​次,而不是兩次。 –

+0

@Jan你可否詳細說明一下。我不是百分百流利的Python,所以我有興趣瞭解更多的知道更多的人。 –

+1

'[x for y in z]'表單創建一個新的列表對象,舊的可以' t被垃圾收集,直到新的構造,所以在一個點上所有的原始字符串和所有修改過的字符串一次存儲在內存中。但是也有'(x for y in z)'形式,它會創建一個生成器。發電機很懶,他們一次執行一個輸入值的表達式並將其返回,因此可以在需要下一個輸入值之前收集它,並且它們永遠不會同時在內存中。在這種情況下,你必須小心,不要太懶,因爲文件也支持懶讀。 –

-1
f = open('./ampo.txt', 'r') 
lines = map(lambda l : 'EDF ' + l, f.readlines()) 
f.close() 
f = open('./ampo.txt', 'w') 
map(lambda l : f.write(l), lines) 
f.close() 
+0

-1:你錯過了需要寫回文件的部分! –

+1

此外,拉姆達不工作 –

+0

錯誤已被修復:) – lollo

0

對於文件沒有太大:

with open('./ampo.txt', 'rb+') as f: 
    x = f.read() 
    f.seek(0,0) 
    f.writelines(('EDF ', x.replace('\n','\nEDF '))) 
    f.truncate() 

需要注意的是,從理論上講,在這種情況下(內容增加),f.truncate()可能並不是真的有必要。因爲with語句應該正確關閉文件,也就是說,在關閉之前在末尾寫入EOF(文件結尾)。
這就是我所看到的例子。
但我很謹慎:我認爲最好放置這個指令。對於內容減少的情況,with語句不會寫入EOF來正確關閉文件,而且文件的遠小於前面的初始EOF,因此尾隨的初始字符將保留在文件中。
因此,如果with語句在內容減少時不寫EOF,爲什麼在內容增加時會寫入EOF?

對於一個大的文件,以避免把RAM中的文件的所有內容一次:

import os 

def addsomething(filepath, ss): 
    if filepath.rfind('.') > filepath.rfind(os.sep): 
     a,_,c = filepath.rpartition('.') 
     tempi = a + 'temp.' + c 
    else: 
     tempi = filepath + 'temp' 

    with open(filepath, 'rb') as f, open(tempi,'wb') as g: 
     g.writelines(ss + line for line in f) 

    os.remove(filepath) 
    os.rename(tempi,filepath) 


addsomething('./ampo.txt','WZE') 
+0

請注意這會覆蓋你的文件。此外,您必須**確保**在開始寫作之前知道要寫的所有內容;寫入過程中的異常會產生損壞的文件。 (這個答案確實有這個問題,因爲python是貪婪評估的。) – ninjagecko

+0

@ninjagecko:在python中有很多很多事情都是**而不是熱切評估的。 –

+0

@eyquem:'f.truncate()'的目的是什麼? – unutbu

0

在這裏你寫一個臨時文件,並將其移動到位的解決方案。如果您要重寫的文件非常大,您可能更喜歡此版本,因爲它避免了將文件內容保留在內存中,因爲版本涉及.read().readlines()。此外,如果在讀取或寫入任何錯誤,原始文件是安全的:

from shutil import move 
from tempfile import NamedTemporaryFile 

filename = './ampo.txt' 
tmp = NamedTemporaryFile(delete=False) 
with open(filename) as finput: 
    with open(tmp.name, 'w') as ftmp: 
     for line in finput: 
      ftmp.write('EDF '+line) 
move(tmp.name, filename)