在Python中读取和覆盖文件


108

目前,我正在使用此:

f = open(filename, 'r+')
text = f.read()
text = re.sub('foobar', 'bar', text)
f.seek(0)
f.write(text)
f.close()

但是问题在于旧文件大于新文件。因此,我最终得到一个新文件,该文件的末尾包含旧文件的一部分。

Answers:


178

如果您不想关闭并重新打开文件,为避免出现竞争情况,可以truncate这样做:

f = open(filename, 'r+')
text = f.read()
text = re.sub('foobar', 'bar', text)
f.seek(0)
f.write(text)
f.truncate()
f.close()

该功能将很可能也更清洁和更安全的使用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.write(text)在后面f.truncate()吗?
volvox

2
@volvox 在此代码f.write(text)之前f.truncate();它写入第text一个,因此在.write()文件光标位于的末尾之后text。继续截断文件将删除此点之后文件可能剩余的所有字节。在这种情况下,最终结果将与您在写入之前被截断一样。
nosklo

对于非常大的文件,将整个文件内容读入内存可能很麻烦。因此,该fileinput模块可以成为首选方法。传递后inplace=1,它将首先将文件移动到临时位置,然后将新文件写入旧文件名路径。在UNIX文件系统上,此移动操作很快,因为它仅移动文件系统inode,而不是全部内容。然后,您可以单独读取和处理每一行,以避免内存过大。:-)
TrinitronX

16

在关闭文件之后text = re.sub('foobar', 'bar', text),重新打开文件以进行写入(从而清除旧内容),然后将更新后的文本写入其中,可能会更容易更整洁。


16

fileinput模块提供了一种inline模式,用于在不使用临时文件等的情况下将更改写入正在处理的文件。该模块很好地封装了通过对象透明地跟踪文件名来循环遍历文件列表中的行的常见操作,行号等,如果您想在循环中检查它们。

import fileinput
for line in fileinput.FileInput("file",inplace=1):
    if "foobar" in line:
         line=line.replace("foobar","bar")
    print line

0

老实说,您可以看一下我构建的该类,它执行基本的文件操作。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)
        

-2

尝试将其写入新文件中。

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()
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.