READING FILE BACKWARDS - Processing files from end to start
Python
#!/usr/bin/env python3
"""
READING FILE BACKWARDS - Processing files from end to start
Demonstrates various techniques for reverse file reading
"""
import os
import tempfile
print("=" * 60)
print("READING FILE BACKWARDS - Reverse Processing")
print("=" * 60)
temp_dir = tempfile.gettempdir()
# Create sample file
sample_file = os.path.join(temp_dir, "sample.txt")
with open(sample_file, 'w') as f:
for i in range(1, 11):
f.write(f"Line {i:02d}: Sample data\n")
print("Created sample file with 10 lines\n")
# Example 1: Read all lines, reverse list
print("1. Read All and Reverse")
print("-" * 40)
with open(sample_file, 'r') as f:
lines = f.readlines()
reversed_lines = lines[::-1]
print("Lines in reverse order:")
for line in reversed_lines:
print(f" {line.rstrip()}")
# Example 2: Using reversed() function
print("\n2. Using reversed() Function")
print("-" * 40)
with open(sample_file, 'r') as f:
lines = f.readlines()
print("Lines in reverse:")
for line in reversed(lines):
print(f" {line.rstrip()}")
# Example 3: Read last N lines (like tail)
print("\n3. Read Last 3 Lines (tail -3)")
print("-" * 40)
n = 3
with open(sample_file, 'r') as f:
lines = f.readlines()
last_n = lines[-n:]
print(f"Last {n} lines:")
for line in last_n:
print(f" {line.rstrip()}")
# Example 4: Process file backwards with seek
print("\n4. Read Backwards Using Seek (Binary Mode)")
print("-" * 40)
def read_backwards_binary(filename, num_lines=5):
"""Read last num_lines using seek"""
with open(filename, 'rb') as f:
# Go to end
f.seek(0, 2)
file_size = f.tell()
lines_found = []
buffer = b''
position = file_size - 1
while position >= 0 and len(lines_found) < num_lines:
f.seek(position)
char = f.read(1)
if char == b'\n' and buffer:
# Found a complete line
line = buffer[::-1].decode('utf-8')
lines_found.append(line)
buffer = b''
else:
buffer += char
position -= 1
# Handle first line (no leading newline)
if buffer and len(lines_found) < num_lines:
line = buffer[::-1].decode('utf-8')
lines_found.append(line)
return lines_found
last_5 = read_backwards_binary(sample_file, 5)
print("Last 5 lines read backwards:")
for line in last_5:
print(f" {line.rstrip()}")
# Example 5: Read file in reverse chunks
print("\n5. Read File in Reverse Chunks")
print("-" * 40)
def read_reverse_chunks(filename, chunk_size=50):
"""Read file in reverse chunks"""
with open(filename, 'rb') as f:
f.seek(0, 2)
file_size = f.tell()
chunks = []
position = file_size
while position > 0:
chunk_start = max(0, position - chunk_size)
chunk_length = position - chunk_start
f.seek(chunk_start)
chunk = f.read(chunk_length)
chunks.append(chunk)
position = chunk_start
return chunks
chunks = read_reverse_chunks(sample_file, 30)
print(f"Read {len(chunks)} chunks in reverse:")
for i, chunk in enumerate(chunks, 1):
print(f" Chunk {i}: {len(chunk)} bytes")
# Example 6: Find last occurrence of pattern
print("\n6. Find Last Occurrence of 'Line 05'")
print("-" * 40)
search_term = "Line 05"
with open(sample_file, 'r') as f:
lines = f.readlines()
# Search from end
for line in reversed(lines):
if search_term in line:
print(f" Found: {line.rstrip()}")
break
# Example 7: Reverse file completely
print("\n7. Create Reversed Copy of File")
print("-" * 40)
reversed_file = os.path.join(temp_dir, "reversed.txt")
with open(sample_file, 'r') as src, open(reversed_file, 'w') as dst:
lines = src.readlines()
for line in reversed(lines):
dst.write(line)
print(f"Created reversed file: {reversed_file}")
with open(reversed_file, 'r') as f:
print("First 3 lines of reversed file:")
for i in range(3):
print(f" {f.readline().rstrip()}")
# Example 8: Character-level reverse
print("\n8. Reverse File Character by Character")
print("-" * 40)
char_reversed_file = os.path.join(temp_dir, "char_reversed.txt")
with open(sample_file, 'r') as src:
content = src.read()
with open(char_reversed_file, 'w') as dst:
dst.write(content[::-1])
print(f"Created character-reversed file")
with open(char_reversed_file, 'r') as f:
sample = f.read(40)
print(f" First 40 chars: {sample}")
# Example 9: Read last non-empty line
print("\n9. Find Last Non-Empty Line")
print("-" * 40)
# Add some empty lines
test_file = os.path.join(temp_dir, "with_empty.txt")
with open(test_file, 'w') as f:
f.write("Line 1\n")
f.write("Line 2\n")
f.write("Line 3\n")
f.write("\n")
f.write("\n")
with open(test_file, 'r') as f:
lines = f.readlines()
last_non_empty = None
for line in reversed(lines):
if line.strip():
last_non_empty = line.rstrip()
break
print(f" Last non-empty line: {last_non_empty}")
# Example 10: Tail-follow simulation (read last few, then new ones)
print("\n10. Simulating 'tail -f' Behavior")
print("-" * 40)
log_file = os.path.join(temp_dir, "growing.log")
# Initial content
with open(log_file, 'w') as f:
for i in range(1, 6):
f.write(f"Initial log line {i}\n")
# Read last 3 lines
with open(log_file, 'r') as f:
lines = f.readlines()
last_3 = lines[-3:]
print("Last 3 lines initially:")
for line in last_3:
print(f" {line.rstrip()}")
# Append more content
with open(log_file, 'a') as f:
for i in range(6, 9):
f.write(f"New log line {i}\n")
# Read only new lines
with open(log_file, 'r') as f:
all_lines = f.readlines()
new_lines = all_lines[len(lines):]
print("\nNewly added lines:")
for line in new_lines:
print(f" {line.rstrip()}")
# Cleanup
for f in [sample_file, reversed_file, char_reversed_file, test_file, log_file]:
if os.path.exists(f):
os.remove(f)
print("\n" + "=" * 60)
print("Key Points:")
print(" - Use [::-1] to reverse list of lines")
print(" - reversed() for memory-efficient reverse iteration")
print(" - seek() for reading specific positions")
print(" - Can reverse entire file or character-level")
print(" - Useful for logs (tail -f behavior)")
print("=" * 60)