Created
August 3, 2016 06:05
-
-
Save f3rdy/32c0b7fb3ee2bf1db0c0c03977f21377 to your computer and use it in GitHub Desktop.
reverse readline
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import os | |
# from: http://bit.ly/2arGvvk | |
def reverse_readline(filename, buf_size=8192): | |
"""a generator that returns the lines of a file in reverse order""" | |
with open(filename) as fh: | |
segment = None | |
offset = 0 | |
fh.seek(0, os.SEEK_END) | |
file_size = remaining_size = fh.tell() | |
while remaining_size > 0: | |
offset = min(file_size, offset + buf_size) | |
fh.seek(file_size - offset) | |
buffer = fh.read(min(remaining_size, buf_size)) | |
remaining_size -= buf_size | |
lines = buffer.split('\n') | |
# the first line of the buffer is probably not a complete line so | |
# we'll save it and append it to the last line of the next buffer | |
# we read | |
if segment is not None: | |
# if the previous chunk starts right from the beginning of line | |
# do not concact the segment to the last line of new chunk | |
# instead, yield the segment first | |
if buffer[-1] is not '\n': | |
lines[-1] += segment | |
else: | |
yield segment | |
segment = lines[0] | |
for index in range(len(lines) - 1, 0, -1): | |
if len(lines[index]): | |
yield lines[index] | |
# Don't yield None if the file was empty | |
if segment is not None: | |
yield segment |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment