Reputation: 17
I'm trying to define a function that outputs the last n lines in a file. The function below seems to mostly work, aside from the fact that the first two lines in fReverse are being joined and I can't figure out why...
example: (I tried putting these in blockquotes instead of code, but it ruins the line formatting)
f =
Darkly I gaze into the days ahead,
And see her might and granite wonders there,
Beneath the touch of Time’s unerring hand,
Like priceless treasures sinking in the sand.
fReverse =
Like priceless treasures sinking in the sand.Beneath the touch of Time’s unerring hand,
And see her might and granite wonders there,
Darkly I gaze into the days ahead,
Code:
def tail(filename, nlines):
'''Returns a list containing the last n lines of the file.'''
f = open(filename, 'r')
fReverse = open('output.txt', 'w')
fReverse.writelines(reversed(f.readlines()))
fReverse.close()
f.close()
fReverse = open('output.txt', 'r')
listFile = []
for i in range(1,nlines+1):
listFile.append(fReverse.readline(),)
fReverse.close()
return listFile
fname = raw_input('What is the name of the file? ')
lines = int(raw_input('Number of lines to display? '))
print "The last %d lines of the file are: \n%s" % (lines, ''.join(tail(fname, lines)))
Upvotes: 0
Views: 129
Reputation: 974
This function can be simplified down quite a bit:
def tail(filename, number_lines):
with open(filename, 'r') as file:
with open('output.txt', 'w') as output:
reversed_lines = file.readlines()[::-1]
output.write('\n'.join([line.strip() for line in reversed_lines]))
return reversed_lines[:number_lines-1]
Upvotes: 1
Reputation: 34047
That's because the last line has no \n
with it at the end ;P
You can try:
lines = reversed([l.strip()+'\n' for l in f])
fReverse.writelines(lines)
Upvotes: 0
Reputation: 208615
The issue here is that the last line of your file does not end with a newline character. So f.readlines()
will be something like the following (note that the final entry does not have the \n
):
['Darkly I gaze into the days ahead,\n',
'And see her might and granite wonders there,\n',
'Beneath the touch of Time’s unerring hand,\n',
'Like priceless treasures sinking in the sand.']
So when you reverse this you end up writing to the file your first "line" doesn't actually write a \n
and fReverse.writelines()
doesn't add a line ending automatically. To fix this, just check to see if the last line from f.readlines()
ends with \n
and add it if necessary:
def tail(filename, nlines):
'''Returns a list containing the last n lines of the file.'''
f = open(filename, 'r')
fReverse = open('output.txt', 'w')
lines = f.readlines()
if not lines[-1].endswith('\n'):
lines[-1] += '\n'
fReverse.writelines(reversed(lines))
fReverse.close()
f.close()
fReverse = open('output.txt', 'r')
listFile = []
for i in range(1,nlines+1):
listFile.append(fReverse.readline(),)
fReverse.close()
return listFile
Upvotes: 0
Reputation: 142216
Easier to use a deque
here:
To reverse the whole file:
from collections import deque
with open('file') as fin:
reversed_lines = deque()
reversed_lines.extendleft(fin)
To display the last n
(but iterating through all lines first):
with open('file') as fin:
last4 = deque(fin, 4)
Upvotes: 4