1

So I have a text file (called 'Numbers') which looks like this:

1 - 2 - 3 - 8 - 5 - 6  
1 - 2 - 3 - 4 - 5 - 6  
1 - 2 - 3 - 4 - 5 - 6  
1 - 2 - 3 - 4 - 5 - 6  

I want to replace the number 8 in the first line with a number 4. How do I do this?
So far I've got the following:

File = open('Numbers.txt','r+')  
for line in File:
  Row = line.split(' - ')
  FourthValue = Row[3]
  NewFourthValue = '4'
  NewLine = line.replace(FourthValue,NewFourthValue)
  File.write(NewLine)
  break
File.close()

Then, it appends the new correct line onto the end of the file like this:

1 - 2 - 3 - 8 - 5 - 6  
1 - 2 - 3 - 4 - 5 - 6  
1 - 2 - 3 - 4 - 5 - 6  
1 - 2 - 3 - 4 - 5 - 61 - 2 - 3 - 4 - 5 - 6

What can I do to make this new line replace the first line?

PM 2Ring
  • 54,345
  • 6
  • 82
  • 182
MiniMo
  • 13
  • 2
  • This should be quite similar, http://stackoverflow.com/questions/39086/search-and-replace-a-line-in-a-file-in-python – J.J. Hakala Jun 26 '16 at 12:13
  • I want it to be much simpler than that, I'm only an amateur programmer. @J.J.Hakala – MiniMo Jun 26 '16 at 12:33
  • you just cannot process a text file in read/write mode. You have to read the data, close, and open the previous file again in writing and write the new data. – Jean-François Fabre Jun 26 '16 at 12:41

2 Answers2

0

Text files are problematic to rewrite because they often have variable length records, however yours is fixed length, so:

fh = open('gash.txt','r+') 

# read the first line
line = fh.readline()
row = line.split(' - ')
fourthValue = row[3]

newFourthValue = '4'
newLine = line.replace(fourthValue, newFourthValue)

At this point the "current file position" is at the start of the next line, so we have to move it back to the start of the current record

fh.seek(0)
fh.write(newLine)

fh.close()

That is very simplistic. The line is question is the first line. If it was anywhere else we would have to remember the file position before each line by using fh.tell(), then using that number in the fh.seek().

EDIT: In reply to the question "If I wanted to replace a value in the 4th line not the first", this replaces the 4 with an 8 on the fourth line.

lineToChange = 4
fieldToChange = 3
newValue = '8'
sep = ' - '
lineno = 0

fh = open('gash.txt','r+')

while True:
    # Get the current file position
    start_pos = fh.tell()

    # read the next line
    line = fh.readline()
    if not line: break          # exit the loop at EOF

    lineno += 1

    if lineno == lineToChange:
        row = line.split(sep)

        # A different replace mechanism
        row[fieldToChange] = newValue
        newLine = sep.join(row)

        # before writing, we must move the file position
        fh.seek(start_pos)
        fh.write(newLine)

fh.close()

Please note this only works because we are replacing a single character with another single character. If we wanted to replace, say, 8 with 10 then this would not work, because now the line length would be different and we would overwrite the start of the next line.

cdarke
  • 42,728
  • 8
  • 80
  • 84
  • Thank you very much. One thing, however, is there a way in which I can control the position of the cursor in the file? So for example, If I wanted to replace a value in the 4th line not the first, can I use fh.tell or fh.seek to help me? @cdarke – MiniMo Jun 26 '16 at 13:52
0

After reading the first line you need to "rewind" the file so you can overwrite the first line.

with open(fname, 'r+') as f:
    row = f.readline()
    row = row.replace('8', '4')
    f.seek(0)
    f.write(row)

Be careful when doing this though, because if the new data isn't exactly the same size as the old data you will mess up the following lines. Generally, it's much simpler & safer to create a new file, copying the (possibly modified) lines from one to the other, but it is nice to know this technique if you ever have to process huge files.

FWIW, my answer here handles the more general case of in-place modification of the data at an arbitrary position in the file.

Community
  • 1
  • 1
PM 2Ring
  • 54,345
  • 6
  • 82
  • 182