2012-12-21 51 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