Search and write to .txt file

Discussion in 'Python' started by Helvin, Aug 11, 2009.

  1. Helvin

    Helvin Guest

    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!
     
    Helvin, Aug 11, 2009
    #1
    1. Advertisements

  2. 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.
     
    Kushal Kumaran, Aug 11, 2009
    #2
    1. Advertisements

  3. 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
     
    Piet van Oostrum, Aug 11, 2009
    #3
  4. 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.
     
    Mark Lawrence, Aug 11, 2009
    #4
  5. Helvin

    Dave Angel Guest

    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
     
    Dave Angel, Aug 11, 2009
    #5
  6. Helvin

    Simon Forman Guest

    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.
     
    Simon Forman, Aug 11, 2009
    #6
    1. Advertisements

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.