我正在使用python为html制作模板更新程序。我读了一行并将其与模板文件进行比较,看看是否有任何需要更新的更改。然后我想把任何更改(如果有的话)写回我刚才读的同一行。
读取文件后,我的文件指针现在位于readline()之后的下一行。无论如何,我可以回写到同一行而无需打开两个文件句柄进行读写吗?
以下是我想要做的代码片段:
cLine = fp.readline()
if cLine != templateLine:
# Here is where I would like to write back to the line I read from
# in cLine
答案 0 :(得分:6)
SO中的许多问题都是尝试读取文件并立即更新。
虽然这在技术上是可行的,但这非常困难。
(文本)文件不是按行排列在磁盘上,而是按字节组织。
问题是,旧行上读取的字节数通常与新行不同,这会弄乱生成的文件。
虽然听起来效率低,但从编程的角度来看,它是最有效的方式。
只读取文件的一面,写入另一面的另一个文件,关闭文件并复制新创建的内容。
或者在内存中创建文件,最后在关闭旧文件后再对旧文件进行书写。
答案 1 :(得分:2)
在操作系统级别,它与Python的外观略有不同 - 从Python看,文件看起来几乎就像一个字符串列表,每个字符串都有任意长度,所以看起来很容易换一行其他不影响其余部分的东西:
l = ["Hello", "world"]
l[0] = "Good bye"
但实际上,任何文件都只是一个字节流,字符串彼此跟随,没有任何“填充”。因此,如果结果字符串与源字符串具有完全相同的长度,则只能就地覆盖数据 - 否则它只会覆盖以下行。
如果是这种情况(您的处理保证不更改字符串的长度),您可以将文件“倒回”到行的开头并用新数据覆盖该行。下面的脚本将文件中的所有行转换为原位大写:
def eof(f):
cur_loc = f.tell()
f.seek(0,2)
eof_loc = f.tell()
f.seek(cur_loc, 0)
if cur_loc >= eof_loc:
return True
return False
with open('testfile.txt', 'r+t') as fp:
while True:
last_pos = fp.tell()
line = fp.readline()
new_line = line.upper()
fp.seek(last_pos)
fp.write(new_line)
print "Read %s, Wrote %s" % (line, new_line)
if eof(fp):
break
有点相关:Undo a Python file readline() operation so file pointer is back in original state
只有当您的输出行保证具有相同的长度时,才会证明这种方法是合理的,例如,当您使用的文件非常庞大时,您必须对其进行修改。
在所有其他情况下,只需在内存中构建输出并立即将其写回来就会更容易,更高效。另一种选择是写入临时文件,然后删除原始文件并重命名临时文件,以便替换原始文件。