【发布时间】:2021-12-07 16:49:39
【问题描述】:
目前我正在使用这个:
f = open(filename, 'r+')
text = f.read()
text = re.sub('foobar', 'bar', text)
f.seek(0)
f.write(text)
f.close()
但问题是旧文件比新文件大。所以我最终得到了一个新文件,它的末尾有旧文件的一部分。
【问题讨论】:
目前我正在使用这个:
f = open(filename, 'r+')
text = f.read()
text = re.sub('foobar', 'bar', text)
f.seek(0)
f.write(text)
f.close()
但问题是旧文件比新文件大。所以我最终得到了一个新文件,它的末尾有旧文件的一部分。
【问题讨论】:
如果您不想关闭并重新打开文件,以避免出现竞争条件,您可以truncate它:
f = open(filename, 'r+')
text = f.read()
text = re.sub('foobar', 'bar', text)
f.seek(0)
f.write(text)
f.truncate()
f.close()
该功能也可能是cleaner and safer 使用open 作为上下文管理器,即使发生错误,它也会关闭文件处理程序!
with open(filename, 'r+') as f:
text = f.read()
text = re.sub('foobar', 'bar', text)
f.seek(0)
f.write(text)
f.truncate()
【讨论】:
f.truncate() 之后有f.write(text) 吗?
f.write(text) 在此代码中位于 f.truncate() 之前;它首先写入text,因此在.write() 之后,文件光标位于text 的末尾。继续截断文件将删除文件在此之后可能具有的任何剩余字节。在这种情况下,最终结果将与您在写入之前截断一样。
fileinput module 可以成为首选方法。当通过inplace=1 时,它会先将文件移动到一个临时位置,然后将一个新文件写入旧文件名路径。这个移动操作在 unix 文件系统上很快,因为它只是移动文件系统inode,而不是全部内容。然后您可以单独读取和处理每一行以避免内存膨胀。 :-)
fileinput 模块具有inplace 模式,用于在不使用临时文件等的情况下将更改写入您正在处理的文件。该模块很好地封装了通过对象循环遍历文件列表中的行的常见操作如果您想在循环中检查它们,它会透明地跟踪文件名、行号等。
from fileinput import FileInput
for line in FileInput("file", inplace=1):
line = line.replace("foobar", "bar")
print(line)
【讨论】:
在text = re.sub('foobar', 'bar', text) 之后关闭文件,重新打开以写入(从而清除旧内容),然后将更新后的文本写入其中,可能会更容易和更整洁。
【讨论】:
我发现先读后写更容易记住。
例如:
with open('file') as f:
data = f.read()
with open('file', 'w') as f:
f.write('hello')
【讨论】:
老实说,你可以看看我构建的这个类,它执行基本的文件操作。 write 方法覆盖并追加保留旧数据。
class IO:
def read(self, filename):
toRead = open(filename, "rb")
out = toRead.read()
toRead.close()
return out
def write(self, filename, data):
toWrite = open(filename, "wb")
out = toWrite.write(data)
toWrite.close()
def append(self, filename, data):
append = self.read(filename)
self.write(filename, append+data)
【讨论】:
尝试将其写入新文件..
f = open(filename, 'r+')
f2= open(filename2,'a+')
text = f.read()
text = re.sub('foobar', 'bar', text)
f.seek(0)
f.close()
f2.write(text)
fw.close()
【讨论】: