Прочитать и перезаписать файл в Python


108

В настоящее время я использую это:

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

Но проблема в том, что старый файл больше нового. Итак, у меня получается новый файл, в конце которого есть часть старого.

Ответы:


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. Продолжение усечения файла приведет к удалению всех оставшихся байтов, которые могут быть у файла после этого момента. В этом случае конечный результат будет таким же, как при усечении перед записью.
носкло

Для очень больших файлов чтение всего содержимого файла в память может стать громоздким. Таким образом, 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

Честно говоря, вы можете взглянуть на этот созданный мной класс, который выполняет основные файловые операции. Метод записи перезаписывает и добавляет старые данные.

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()
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.