大きなtxtファイルからN行を取得するには、pythonを使用する必要があります。これらのファイルは、基本的にタブ区切りのテーブルです。私のタスクには次の制約があります。
- これらのファイルにはヘッダーが含まれる場合があります (複数行のヘッダーを持つものもあります)。
- ヘッダーは同じ順序で出力に表示される必要があります。
- 各行は 1 回だけ取得できます。
- 現在、最大のファイルは約 150GB (約 60 000 000 行) です。
- ファイル内の行の長さはほぼ同じですが、ファイルによって異なる場合があります。
- 私は通常、5000行のランダム行を取得します(最大1000,000行が必要になる場合があります)
現在、私は次のコードを書いています:
inputSize=os.path.getsize(options.input)
usedPositions=[] #Start positions of the lines already in output
with open(options.input) as input:
with open(options.output, 'w') as output:
#Handling of header lines
for i in range(int(options.header)):
output.write(input.readline())
usedPositions.append(input.tell())
# Find and write all random lines, except last
for j in range(int(args[0])):
input.seek(random.randrange(inputSize)) # Seek to random position in file (probably middle of line)
input.readline() # Read the line (probably incomplete). Next input.readline() results in a complete line.
while input.tell() in usedPositions: # Take a new line if current one is taken
input.seek(random.randrange(inputSize))
input.readline()
usedPositions.append(input.tell()) # Add line start position to usedPositions
randomLine=input.readline() # Complete line
if len(randomLine) == 0: # Take first line if end of the file is reached
input.seek(0)
for i in range(int(options.header)): # Exclude headers
input.readline()
randomLine=input.readline()
output.write(randomLine)
このコードは正しく動作しているようです。
seek() が最も長い行の位置を返す可能性が高く、次の行が出力に書き込まれるため、このコードが入力の最も長い行に続く行を好むことは承知しています。入力ファイルの行はほぼ同じ長さであるため、これは関係ありません。また、Nが入力ファイルの行数よりも大きい場合、このコードが無限ループになることも認識しています。行数の取得には時間がかかるため、このチェックは実装しません。
RAM と HDD の制限は関係ありません。プログラムの速度だけが気になります。このコードをさらに最適化する方法はありますか? それとも、より良いアプローチがありますか?
編集: 明確にするために、1 つのファイル内の行の長さはほぼ同じです。ただし、このスクリプトを実行する必要がある複数のファイルがあり、これらのファイルの行の平均の長さは異なります。たとえば、ファイル A は 1 行あたり最大 100 文字、ファイル B は 1 行あたり最大 50000 文字の場合があります。ファイルの平均行長は事前にわかりません。