compie
compie

Reputation: 10526

Read and overwrite a file in Python

Currently I'm using this:

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

But the problem is that the old file is larger than the new file. So I end up with a new file that has a part of the old file on the end of it.

Upvotes: 154

Views: 201961

Answers (7)

SKO
SKO

Reputation: 50

To anyone who wants to read and overwrite by line, refer to this answer. https://stackoverflow.com/a/71285415/11442980

filename = input("Enter filename: ")
with open(filename, 'r+') as file:
    lines = file.readlines()
    file.seek(0)
    for line in lines:
        value = int(line)
        file.write(str(value + 1))
    file.truncate()

Upvotes: 0

Amy Dowling
Amy Dowling

Reputation: 41

I find it easier to remember to just read it and then write it.

For example:

with open('file') as f:
    data = f.read()
with open('file', 'w') as f:
    f.write('hello')

Upvotes: 4

ghostdog74
ghostdog74

Reputation: 342293

The fileinput module has an inplace mode for writing changes to the file you are processing without using temporary files etc. The module nicely encapsulates the common operation of looping over the lines in a list of files, via an object which transparently keeps track of the file name, line number etc if you should want to inspect them inside the loop.

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

Upvotes: 22

CodinGuy
CodinGuy

Reputation: 31

Honestly you can take a look at this class that I built which does basic file operations. The write method overwrites and append keeps old data.

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)
        

Upvotes: -2

nosklo
nosklo

Reputation: 222802

If you don't want to close and reopen the file, to avoid race conditions, you could truncate it:

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

The functionality will likely also be cleaner and safer using open as a context manager, which will close the file handler, even if an error occurs!

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

Upvotes: 239

sk7979
sk7979

Reputation: 140

Try writing it in a new file..

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()

Upvotes: -2

Il-Bhima
Il-Bhima

Reputation: 10880

Probably it would be easier and neater to close the file after text = re.sub('foobar', 'bar', text), re-open it for writing (thus clearing old contents), and write your updated text to it.

Upvotes: 16

Related Questions