File Reading , Reverse Direction (fwd)

Dr. David Mertz mertz at gnosis.cx
Fri Jul 27 13:09:02 EDT 2001


Ratnakar Malla <rmalla1 at lsu.edu> wrote:
|I need to read from a very long file. But the only information I am
|interested is
|2 lines at the bottom of the file.
|1) Can i read the file in the reverse direction , so that I dont lose
|time?

OK... shameless plug, in my forthcoming book _Text Processing in Python_
(still a number of months away), I show this example program to do what
Ratnakar requests.  HTH:

#---------- read_backwards.py ----------#
# Read blocks of a file from end to beginning.
# Blocks may be defined by any delimiter, but the
#  constants LINE and PARA are useful ones.
# Works much like the file object method '.readline()':
#  repeated calls continue to get "next" part, and
#  function returns empty string once BOF is reached.

# Define constants
LINE = '\n'
PARA = '\n\n'
READSIZE = 1000

# Global variables
buffer = ''

def read_backwards(fh, mode=LINE, sizehint=READSIZE, _init=[0]):
    """Read blocks of file backwards (return empty string when done)"""
    # Trick of mutable default argument to hold state between calls
    if not _init[0]:
        fh.seek(0,2)
        _init[0] = 1
    # Find a block (using global buffer)
    global buffer
    while 1:
        # first check for block in buffer
        delim = buffer.rfind(mode)
        if delim <> -1:     # block is in buffer, return it
            block = buffer[delim+len(mode):]
            buffer = buffer[:delim]
            return block
        elif fh.tell()==0:  # BOF reached, return remainder (or empty string)
            block = buffer
            buffer = ''
            return block
        else:               # Read some more data into the buffer
            readsize = min(fh.tell(),sizehint)
            fh.seek(-readsize,1)
            buffer = fh.read(readsize) + buffer
            fh.seek(-readsize,1)

#-- Self test of read_backwards()
if __name__ == '__main__':
    # Let's create a test file to read in backwards
    open('lines','w').write('\n'.join(['--- %d ---'%n for n in range(15)]))
    # Now open for reading backwards
    fh = open('lines','rb')
    # Read the blocks in, one per call (block==line by default)
    block = read_backwards(fh)
    while block:
        print block
        block = read_backwards(fh)





More information about the Python-list mailing list