Skip to content

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)