Прочитайте та перезапишіть файл у 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()?
вольвокс

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

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

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.