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

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

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

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


person compie    schedule 11.03.2010    source источник


Ответы (6)


Если вы не хотите закрывать и повторно открывать файл, чтобы избежать состояния гонки, вы можете _ 1_ это:

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()
person nosklo    schedule 11.03.2010
comment
Чтобы прояснить ситуацию - должен ли ваш второй клип иметь f.write(text) после f.truncate()? - person volvox; 09.04.2019
comment
@volvox f.write(text) в этом коде стоит перед f.truncate(); он сначала записывает text, поэтому после .write() файловый курсор располагается в конце text. Продолжение усечения файла приведет к удалению всех оставшихся байтов, которые могут быть у файла после этого момента. В этом случае конечный результат будет таким же, как если бы вы усекали его перед записью. - person nosklo; 10.04.2019
comment
Для очень больших файлов чтение всего содержимого файла в память может стать громоздким. Поэтому предпочтительным методом может стать fileinput module. Если передано inplace=1, он сначала переместит файл во временное расположение, а затем запишет новый файл по старому пути к имени файла. Эта операция перемещения выполняется быстро в файловых системах unix, потому что она перемещает только файловую систему inode, а не все содержимое. Затем вы можете читать и обрабатывать каждую строку по отдельности, чтобы избежать раздувания памяти. :-) - person TrinitronX; 28.12.2019

Модуль fileinput имеет режим inplace для записи изменений в файл, который вы обрабатываете. без использования временных файлов и т. д. Модуль прекрасно инкапсулирует обычную операцию перебора строк в списке файлов с помощью объекта, который прозрачно отслеживает имя файла, номер строки и т. д., если вы хотите проверить их внутри цикла.

from fileinput import FileInput
for line in FileInput("file", inplace=1):
    line = line.replace("foobar", "bar")
    print(line)
person ghostdog74    schedule 11.03.2010

Возможно, было бы проще и аккуратнее закрыть файл после text = re.sub('foobar', 'bar', text), повторно открыть его для записи (таким образом очистив старое содержимое) и записать в него обновленный текст.

person Il-Bhima    schedule 11.03.2010

Мне легче не забыть просто прочитать это, а затем написать.

Например:

with open('file') as f:
    data = f.read()
with open('file', 'w') as f:
    f.write('hello')
person Amy Dowling    schedule 11.10.2020

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

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)
        
person CodinGuy    schedule 01.07.2020

Попробуйте записать его в новый файл ..

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()
person sk7979    schedule 29.06.2016