Search and write to .txt file


H

Helvin

Hi everyone,

I am writing some python script that should find a line which contains
'1' in the data.txt file, then be able to move a certain number of
lines down, before replacing a line. At the moment, I am able to find
the line '1', but when I use f.seek to move, and then rewrite, what I
write goes to the end of the .txt file, instead of being adjusted by
my f.seek.

Do you know what way I should take?

Data.txt is a file of 3 lines:
line1
line2
line3

Code:

with open('data.txt', 'r+') as f:
firstread = f.readlines() # Take a snapshot of initial file

f.seek(0,0) # Go back to beginning and search
for line in f:
print line
if line.find('1'):
print 'line matched'
f.seek(1,1) # Move one space along
f.write('house\n') # f.write overwrites the exact
number of bytes.
break # leave loop once '1' is found

f.seek(0,0) # Go back to beginning, and read
data.txt again
lastread = f.readlines()

print 'firstread is', firstread
print 'lastread is', lastread

This shouldn't be too difficult, but I don't know how. > <
Help appreciated!
 
Ad

Advertisements

K

Kushal Kumaran

Hi everyone,

I am writing some python script that should find a line which contains
'1' in the data.txt file, then be able to move a certain number of
lines down, before replacing a line. At the moment, I am able to find
the line '1', but when I use f.seek to move, and then rewrite, what I
write goes to the end of the .txt file, instead of being adjusted by
my f.seek.

Do you know what way I should take?

It might be easier to read the file into a list of lines (using
readlines, as you do in your code already), make your change there and
write it back to a file. If your file is indeed as small as you
indicate below, that should be significantly easier.
 
P

Piet van Oostrum

Helvin said:
H> Hi everyone,
H> I am writing some python script that should find a line which contains
H> '1' in the data.txt file, then be able to move a certain number of
H> lines down, before replacing a line. At the moment, I am able to find
H> the line '1', but when I use f.seek to move, and then rewrite, what I
H> write goes to the end of the .txt file, instead of being adjusted by
H> my f.seek.
H> Do you know what way I should take?
H> Data.txt is a file of 3 lines:
H> line1
H> line2
H> line3
H> with open('data.txt', 'r+') as f:
H> firstread = f.readlines() # Take a snapshot of initial file
H> f.seek(0,0) # Go back to beginning and search
H> for line in f:
H> print line
H> if line.find('1'):
H> print 'line matched'
H> f.seek(1,1) # Move one space along
H> f.write('house\n') # f.write overwrites the exact
H> number of bytes.
H> break # leave loop once '1' is found

Mixing an iterator on the file with direct calls (seek/write) isn't
going to work. The iterator does read ahead which causes the file
position not to be what you think it is.

See:
.... for line in f:
.... print line, f.tell()
....
line1
18
line2
18
line3
18
 
M

Mark Lawrence

Helvin said:
Hi everyone,

I am writing some python script that should find a line which contains
'1' in the data.txt file, then be able to move a certain number of
lines down, before replacing a line. At the moment, I am able to find
the line '1', but when I use f.seek to move, and then rewrite, what I
write goes to the end of the .txt file, instead of being adjusted by
my f.seek.

Do you know what way I should take?

Data.txt is a file of 3 lines:
line1
line2
line3

Code:

with open('data.txt', 'r+') as f:
firstread = f.readlines() # Take a snapshot of initial file

f.seek(0,0) # Go back to beginning and search
for line in f:
print line
if line.find('1'):
print 'line matched'
f.seek(1,1) # Move one space along
f.write('house\n') # f.write overwrites the exact
number of bytes.
break # leave loop once '1' is found

f.seek(0,0) # Go back to beginning, and read
data.txt again
lastread = f.readlines()

print 'firstread is', firstread
print 'lastread is', lastread

This shouldn't be too difficult, but I don't know how. > <
Help appreciated!
You can't mix and match the file iterator "for line in f" with the seek
method. You already have the data in firstread, why not process it from
there, i.e. "for line in firstread". Also look at the docs for the find
method, it doesn't return what you think it does.
 
D

Dave Angel

Piet said:
Mixing an iterator on the file with direct calls (seek/write) isn't
going to work. The iterator does read ahead which causes the file
position not to be what you think it is.

See:


... for line in f:
... print line, f.tell()
...
line1
18
line2
18
line3
18
In addition to the buffering involved in the read loop, trying to
position ahead some number of lines would be rather error prone, since
this is a text file, with varying length lines, and the \n character
might occupy one byte on some OS, and two bytes on others (Windows). If
you feel you must do it in-place, then switch the file mode to binary,
and use read(), not readline(), keeping track of your own position at
all times.

As was already suggested by Kushal, if the file is small enough to just
use readlines() and manipulate that list, I'd do that. If not, I'd scan
through the file, creating a new one, creating a new one as you go, then
rename the new one back when finished. Actually, I'd create a new one
even in the first case, in case of a crash while rewriting the file.


DaveA
 
Ad

Advertisements

S

Simon Forman

Hi everyone,

I am writing some python script that should find a line which contains
'1' in the data.txt file, then be able to move a certain number of
lines down, before replacing a line. At the moment, I am able to find
the line '1', but when I use f.seek to move, and then rewrite, what I
write goes to the end of the .txt file, instead of being adjusted by
my f.seek.

Do you know what way I should take?

Data.txt is a file of 3 lines:
   line1
   line2
   line3

Code:

   with open('data.txt', 'r+') as f:
       firstread = f.readlines()   # Take a snapshot of initial file

       f.seek(0,0)    # Go back to beginning and search
       for line in f:
           print line
           if line.find('1'):
               print 'line matched'
               f.seek(1,1)       # Move one space along
               f.write('house\n')     # f.write overwrites the exact
number of bytes.
               break                    # leave loop once '1' is found

       f.seek(0,0)              # Go back to beginning, and read
data.txt again
       lastread = f.readlines()

       print 'firstread is', firstread
       print 'lastread is', lastread

This shouldn't be too difficult, but I don't know how. > <
Help appreciated!

There's a bug in this line:

if line.find('1'):

the string find() method returns an integer, which will be -1 if the
substring is not found. In python -1 is treated as True (only 0 is
False) so your if statement will always succeed unless '1' is the
first character on the line.

HTH,
~Simon


P.S. you can use the help() command in the python interpreter to get
docs on most things:

Help on method_descriptor:

find(...)
S.find(sub [,start [,end]]) -> int

Return the lowest index in S where substring sub is found,
such that sub is contained within s[start:end]. Optional
arguments start and end are interpreted as in slice notation.

Return -1 on failure.
 
Ad

Advertisements


Top