ファイルの読み書き時にポインタの位置を自由に移動できる`seek()`メソッドについて、具体的な使い方と実践的なコード例を交えて解説します。

seek()メソッドの基本

`seek()`メソッドは、ファイル内のポインタ位置を指定したバイト数だけ移動させることができます。構文は以下の通りです:

file.seek(offset, whence=0)
  • offset: 移動するバイト数
  • whence: 開始位置(省略可能)

- 0: ファイルの先頭から(デフォルト)

- 1: 現在の位置から

- 2: ファイルの末尾から

基本的な使用例

# ファイルを開く
with open('example.txt', 'r') as f:
    # 最初の5バイト分移動
    f.seek(5)
    # 現在位置から読み取り
    content = f.read()

主な使用シーン

1. ファイルの特定位置から読み取り

with open('data.txt', 'r') as f:
    # 10バイト目から読み取り開始
    f.seek(10)
    data = f.read(5)  # 5バイト分読み取り

2. ファイルの末尾からの読み取り

with open('log.txt', 'r') as f:
    # 末尾から10バイト前に移動
    f.seek(-10, 2)
    last_lines = f.read()

3. ファイル内の移動と上書き

with open('text.txt', 'r+') as f:
    # 特定位置に移動して上書き
    f.seek(20)
    f.write('new content')

よくあるエラーと解決策

1. 負の値によるシーク

# エラーの例
with open('file.txt', 'r') as f:
    f.seek(-10)  # エラー発生

# 正しい使用法
with open('file.txt', 'r') as f:
    f.seek(-10, 2)  # 末尾から10バイト前

2. バイナリモードとテキストモード

# テキストモードでのエラー
with open('file.txt', 'r') as f:
    f.seek(5, 1)  # エラー発生

# バイナリモードでの正しい使用
with open('file.txt', 'rb') as f:
    f.seek(5, 1)  # OK

実践的なユースケース

ログファイルの最新部分の読み取り

def read_last_lines(filename, bytes_to_read=100):
    with open(filename, 'rb') as f:
        f.seek(0, 2)  # 末尾に移動
        total_size = f.tell()  # 全体のサイズを取得
        
        # 指定バイト数か、ファイルサイズの小さい方を選択
        read_size = min(bytes_to_read, total_size)
        f.seek(-read_size, 2)
        
        return f.read().decode('utf-8')

ファイル内容の部分更新

def update_content_at_position(filename, position, new_content):
    with open(filename, 'r+') as f:
        f.seek(position)
        f.write(new_content)

注意点とベストプラクティス

1. テキストモードでは`whence=0`(ファイル先頭からの移動)のみサポート

2. バイナリモードではすべての`whence`値が使用可能

3. ファイルサイズを超える移動は想定外の動作を引き起こす可能性あり

4. 大きなファイルの場合はメモリ使用量に注意

`seek()`メソッドを適切に使用することで、効率的なファイル操作が可能になります。特に大きなファイルを扱う際や、特定位置のデータにアクセスする必要がある場合に役立ちます。