0

I have a text file. I would like to use python v3.6 to read the text file line by line, append each line with a sub-string and replace the existing line with the appended string line by line.

To be clearer, here is the original text file;

1,2,3
4,5,6

The desired output text file should look like this;

appended_text,1,2,3
appended_text,4,5,6

This is how my code looks like;

with open(filename, 'r+') as myfile:
    for line in myfile:
        newline = "appended_text" + "," + line            
        myfile.write(newline)

I did not get what I want. What I got instead was a huge line of text appended at the end of the file. How should the code be modified? Is there a better way to implement what I want?

user3848207
  • 3,737
  • 17
  • 59
  • 104

5 Answers5

4

There's no such thing as "replacing an existing line" in a file. For what you want to do, you have to write a new file with the modified content and then replace the old file with the new one. Example code:

with open("old.file") as old, open("new.file", "w") as new:
    for line in old:        
        line = modify(line.lstrip())
        new.write(line + "\n")
os.rename("new.file", "old.file")
chepner
  • 497,756
  • 71
  • 530
  • 681
bruno desthuilliers
  • 75,974
  • 6
  • 88
  • 118
2

You cannot, in general, modify a file in place like this. Instead, write a copy to a new file, then replace the original with the new one.

with open(filename, 'r') as myfile:
    with open("copy", 'w') as newfile:
        for line in myfile:
            newline = "appended_text" + "," + line            
            newfile.write(newline)

os.rename("copy", filename)
chepner
  • 497,756
  • 71
  • 530
  • 681
1

Here is what I would do:

with open(filename, 'r+') as f:
    lines = []
    for line in f:
        lines.append("appended_text" + "," + line)
    f.seek(0)
    for line in lines:
        f.write(line)

For example:

sample.txt before:

hello
there
world

code:

fp = r"C:\Users\Me\Desktop\sample.txt"
with open(fp, 'r+') as f:
    lines = []
    for line in f:
        lines.append("something," + line)
        lines.append(line.strip() + ",something\n")
    f.seek(0)
    for line in lines:
        f.write(line)

sample.txt after:

something,hello
hello,something
something,there
there,something
something,world
world,something

A couple of notes:

  1. This assumes you are going to append to the front of each line. Thus the newline ('\n') is kept with the original content of each line. If you are appending to the end, I would change to: lines.append(line.strip() + "," + "appended_text").
  2. You can probably combine "appended_text" and the "," to "appended_text,". Unless "appended_text" is a varable like appended_text = "something".
  3. Though contextually correct as a solution to your question; I'd look to writing a new file with the changes desired and replacing the old one with the new one as recommend in other answers.
pstatix
  • 3,611
  • 4
  • 18
  • 40
  • 1
    This isn't safe. If there is an error during one of the writes, you could wind up with a corrupted file. It's better to ensure the *entire* file can be written safely first, then replace the old file with the new in one atomic move. – chepner Sep 28 '17 at 12:04
  • @chepner What error would one encounter? Iterating and storing values in a container, seeking and overwriting is no different than opening the same file after a read and truncating with the `'w'` mode. – pstatix Sep 28 '17 at 12:09
  • That's right; they are *both* unsafe. IO errors are almost by definition unpredictable; you don't want to risk overwriting the original file until the new file is *completely* written. – chepner Sep 28 '17 at 12:14
  • @chepner Fair point. I'll leave the answer since it is contextually correct as a solution to the posed question. Though I've updated it to make note. – pstatix Sep 28 '17 at 12:20
1

If you want to write it to the same file:

f = open(filename, 'r')
lines = f.readlines()
f.close()

lines = ['appended_text, ' + l for l in lines]

f = open(filename, 'w')
f.writelines(lines)
f.close()
Ahmed Dhanani
  • 841
  • 1
  • 11
  • 32
-1

I believe to get what you want you need to put myfile.readlines() before your for loop.

liam
  • 1,918
  • 3
  • 22
  • 28