If you combine rev | tac
(as in your case) then the result is a file in the reversed byte order (ignoring possible differences in whitespace). To get the desired output, you could read starting from the last byte and moving to the beginning of the file one byte at a time.
You could read/write all at once:
with open('words.txt', 'rb') as file, open('reverse.txt', 'wb') as outfile:
outfile.write(file.read()[::-1])
Or one byte at a time:
#!/usr/bin/env python
"""Print file in the reverse byte order."""
import os
with open('words.txt', 'rb') as file, open('reverse.txt', 'wb') as outfile:
file.seek(0, os.SEEK_END) # move to the end
for position in range(file.tell() - 1, -1, -1): # from last position
file.seek(position, os.SEEK_SET) # move back
outfile.write(file.read(1)) # read/write byte
The disadvantage is that reading one byte at a time is slow in Python. The advantage is that it also supports files that do not fit in memory.
mmap
module allows to treat a file as a string:
#!/usr/bin/env python3
from mmap import ACCESS_READ, mmap
with open('words.txt') as f, mmap(f.fileno(), 0, access=ACCESS_READ) as s:
with open('reverse.txt', 'wb') as outfile:
for i in range(len(s) - 1, -1, -1):
outfile.write(s[i:i+1])
You could also read a block at time. See Most efficient way to search the last x lines of a file in python.