2011-10-03 79 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)