Skip to content

FILE POSITION AND SEEKING - Navigating within files

Python
#!/usr/bin/env python3
"""
FILE POSITION AND SEEKING - Navigating within files
Demonstrates seek(), tell(), and random access
"""

import os
import tempfile

print("=" * 60)
print("FILE POSITION AND SEEKING - Random Access")
print("=" * 60)

temp_dir = tempfile.gettempdir()
test_file = os.path.join(temp_dir, "positions.txt")

# Create test file
with open(test_file, 'w') as f:
    f.write("0123456789ABCDEFGHIJ")

# Example 1: tell() - get current position
print("\n1. Using tell() to Get Position")
print("-" * 40)
with open(test_file, 'r') as f:
    print(f"  Initial position: {f.tell()}")
    f.read(5)
    print(f"  After reading 5 chars: {f.tell()}")
    f.read(3)
    print(f"  After reading 3 more: {f.tell()}")

# Example 2: seek() - move to specific position
print("\n2. Using seek() to Move Position")
print("-" * 40)
with open(test_file, 'r') as f:
    f.seek(10)
    char = f.read(1)
    print(f"  Position 10: '{char}'")

    f.seek(0)
    char = f.read(1)
    print(f"  Position 0: '{char}'")

    f.seek(5)
    char = f.read(1)
    print(f"  Position 5: '{char}'")

# Example 3: Seek from different reference points
print("\n3. Seek Reference Points (Binary Mode)")
print("-" * 40)
with open(test_file, 'rb') as f:
    # From beginning (0)
    f.seek(5, 0)
    print(f"  seek(5, 0) from start: {f.read(1).decode()}")

    # From current position (1)
    f.seek(3, 1)
    print(f"  seek(3, 1) from current: {f.read(1).decode()}")

    # From end (2)
    f.seek(-5, 2)
    print(f"  seek(-5, 2) from end: {f.read(1).decode()}")

# Example 4: Reading file backwards
print("\n4. Reading File Backwards")
print("-" * 40)
with open(test_file, 'rb') as f:
    # Get file size
    f.seek(0, 2)  # Go to end
    file_size = f.tell()

    result = []
    for i in range(file_size, 0, -1):
        f.seek(i - 1)
        char = f.read(1).decode()
        result.append(char)

    print(f"  Original: 0123456789ABCDEFGHIJ")
    print(f"  Reversed: {''.join(result)}")

# Example 5: Random access read
print("\n5. Random Access - Reading Specific Positions")
print("-" * 40)
positions = [0, 5, 10, 15, 19]
with open(test_file, 'r') as f:
    for pos in positions:
        f.seek(pos)
        char = f.read(1)
        print(f"  Position {pos:2d}: '{char}'")

# Example 6: Overwriting specific positions
print("\n6. Overwriting at Specific Positions")
print("-" * 40)
work_file = os.path.join(temp_dir, "overwrite.txt")

# Create original
with open(work_file, 'w') as f:
    f.write("XXXXXXXXXX")

print("  Original: XXXXXXXXXX")

# Overwrite specific positions
with open(work_file, 'r+') as f:  # r+ = read and write
    f.seek(2)
    f.write("AB")
    f.seek(7)
    f.write("CD")

with open(work_file, 'r') as f:
    print(f"  Modified: {f.read()}")

# Example 7: Inserting data is tricky
print("\n7. Inserting Data (Requires Rewrite)")
print("-" * 40)
insert_file = os.path.join(temp_dir, "insert.txt")

with open(insert_file, 'w') as f:
    f.write("ABCDEF")

print("  Original: ABCDEF")
print("  Want to insert 'XXX' at position 3")

# Read, modify, write back
with open(insert_file, 'r') as f:
    content = f.read()

new_content = content[:3] + "XXX" + content[3:]

with open(insert_file, 'w') as f:
    f.write(new_content)

with open(insert_file, 'r') as f:
    print(f"  Result: {f.read()}")

# Example 8: Reading chunks at specific positions
print("\n8. Reading Chunks at Positions")
print("-" * 40)
chunk_file = os.path.join(temp_dir, "chunks.txt")

with open(chunk_file, 'w') as f:
    f.write("AAA|BBB|CCC|DDD|EEE")

chunks = [(0, 3), (4, 3), (8, 3), (12, 3), (16, 3)]
with open(chunk_file, 'r') as f:
    for pos, length in chunks:
        f.seek(pos)
        chunk = f.read(length)
        print(f"  Position {pos:2d}, length {length}: '{chunk}'")

# Example 9: File size and navigation
print("\n9. Getting File Size with Seek")
print("-" * 40)
with open(test_file, 'rb') as f:
    # Method 1: seek to end
    f.seek(0, 2)
    size = f.tell()
    print(f"  File size: {size} bytes")

    # Go back to start
    f.seek(0)
    print(f"  Back at position: {f.tell()}")

# Cleanup
for f in [test_file, work_file, insert_file, chunk_file]:
    if os.path.exists(f):
        os.remove(f)

print("\n" + "=" * 60)
print("Key Points:")
print("  - tell() returns current position")
print("  - seek(offset, whence) moves position")
print("  - whence: 0=start, 1=current, 2=end")
print("  - Mode 'r+' allows read and write")
print("  - Binary mode needed for non-zero whence")
print("=" * 60)