ファイルの最後の n 行を読み取ることは、tail -n を思い出させる一般的な要件です。 Unix 系システムのコマンド。これを達成するには、この機能を提供できる効率的な方法を見つける必要があります。
提案されたアプローチの 1 つは、平均ライン長を推定し、十分な長さになるまで徐々に長くすることです。行数が読み取られます。この方法は合理的ではありますが、行の長さの推定に依存しており、特定のシナリオではパフォーマンスが低下する可能性があります。
より堅牢な代替方法には、ブロック単位でファイルを反復処理することが含まれます。ブロック サイズは最適なパフォーマンスが得られるように調整でき、この方法は行の長さに関する仮定に依存しません。必要なラインの総数が得られるまで、ブロックの読み取りを続けます。この手法により、さまざまなファイル サイズや行長にわたって一貫した信頼性の高いパフォーマンスが保証されます。
このブロックベースの方法を使用するときは、システムのサイズと比較してファイルのサイズを考慮することが重要です。オペレーティング システム (OS) のブロック サイズ。ファイルが単一の OS ブロックより小さい場合、この方法では冗長な読み取りが発生し、パフォーマンスが低下する可能性があります。このような場合、ブロック サイズを OS のブロック サイズに合わせることで改善が得られる可能性があります。ただし、大きなファイルの場合、この最適化は重大な影響を及ぼさない可能性があります。
提案された代替アプローチは、次のように Python で実装できます。
def tail(f, lines=20): """Reads the last n lines from a file.""" BLOCK_SIZE = 1024 f.seek(0, 2) block_end_byte = f.tell() lines_to_go = lines block_number = -1 blocks = [] while lines_to_go > 0 and block_end_byte > 0: if (block_end_byte - BLOCK_SIZE > 0): f.seek(block_number*BLOCK_SIZE, 2) blocks.append(f.read(BLOCK_SIZE)) else: f.seek(0, 0) blocks.append(f.read(block_end_byte)) lines_found = blocks[-1].count(b'\n') # Edit for Python 3.2 and up lines_to_go -= lines_found block_end_byte -= BLOCK_SIZE block_number -= 1 all_read_text = b''.join(reversed(blocks)) # Edit for Python 3.2 and up return b'\n'.join(all_read_text.splitlines()[-lines:]) # Edit for Python 3.2 and up
この実装では、読み取る行数を指定できるため、柔軟で汎用性の高いソリューションになります。堅牢性とパフォーマンスを優先し、行の長さやファイル サイズに関する仮定を回避します。
以上がPython でファイルの最後の N 行を効率的に読み取るにはどうすればよいですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。