Saturday, 10 October 2009

Reverse File Iterator in python

import os
def rblocks(f, blocksize=4096):
"""Read file as series of blocks from end of file to start.
The data itself is in normal order, only the order of the blocks is reversed.
ie. "hello world" -> ["ld","wor", "lo ", "hel"]
Note that the file must be opened in binary mode.
"""
if 'b' not in f.mode.lower():
raise Exception("File must be opened using binary mode.")
size = os.stat(f.name).st_size
fullblocks, lastblock = divmod(size, blocksize)
# The first(end of file) block will be short, since this leaves
# the rest aligned on a blocksize boundary. This may be more
# efficient than having the last (first in file) block be short
f.seek(-lastblock,2)
yield f.read(lastblock)
for i in xrange(fullblocks-1,-1, -1):
f.seek(i * blocksize)
yield f.read(blocksize)
def rlines(f, keepends=False):
"""Iterate through the lines of a file in reverse order.
If keepends is true, line endings are kept as part of the line.
"""
buf = ''
for block in rblocks(f):
buf = block + buf
lines = buf.splitlines(keepends)
# Return all lines except the first (since may be partial)
if lines:
lines.reverse()
buf = lines.pop() # Last line becomes end of new first line.
for line in lines:
yield line
yield buf # First line.
file = open("example.txt", 'rb')
for line in rlines(file):
print line
view raw gistfile1.py hosted with ❤ by GitHub

No comments:

Post a Comment