2009-08-10 11 views
2

私は、200,000行以上の大きなテキストファイルを持っています。たとえば、10.000〜20.000行。C++の大きなテキストファイルから部分データを読み込む方法

重要:性能に関する問題のために、これらの行を抽出するためにフルファイルを開いて検索する必要はありません。

これは可能ですか?

+0

私はそれがFortranで行われているのを見て、データカウンター(200万行)からファイルを読み取らなければなりませんでした。だから私はそれが実行可能であると確信しています – dassouki

答えて

1

すべての行が同じ長さであることが分かっていない限り、改行を数えるためにファイルを検索する必要があります(オフセット= line_number * line_size_in_bytesを検索することができます。ただし、line_numberは0からline_size_in_bytesまで行内のすべての文字)。

行が可変長/不明な長さの場合は、一度読んでいれば、各行の開始オフセットにインデックスを付けることができます。これにより、後続の読み取りが特定の行の先頭にシークできるようになります。

6

行が固定長の場合は、特定のバイト位置を探して、必要な行だけをロードすることができます。行が可変長である場合、探している行を見つける唯一の方法は、ファイルを解析して行末マーカーの数を数えることです。ファイルが頻繁に変更されない場合は、この解析を一度実行して、各行のバイト位置のインデックスを保持して将来のアクセスを高速化することで十分なパフォーマンスを得ることができるかもしれません(おそらく、プログラムが実行されるたびに実行されます)。

+1

注意:一部のファイル形式には、開始時または時には終わり近くにインデックスの耳が含まれています。次に、インデックスを読み、それを使って必要なデータの開始位置を計算します。はい、これはバイナリ形式ではより簡単で一般的ですが、テキスト形式で行っています。 – dmckee

+0

+1答えは @dmckee:最初のインデックスは本当の問題ではないようですか?最後にはおそらく終わりを追求することができ、おそらくインデックスのサイズを知っているので、大きな問題ではないようですね。 – neuro

+0

@neuro:最後のインデックスの最後の要素は、インデックスの先頭の固定サイズのオフセットでなければなりません。あなたは最後まで追求し、既知の金額でバックアップし、インデックスのオフセットを読み取り、インデックスに行き、そこから進みます。明らかだよね? :) – dmckee

0

これらの行がすべて同じ長さである場合、特定の行のオフセットを計算し、それらのバイトだけを読み取ることができます。

行の長さが変化している場合は、ファイル全体を読み取って行数を数えなければなりません。行終了文字は、ファイル内の任意のバイトです。

0

ラインが固定長である場合、オフセットを計算するだけで問題はありません。

そうでない場合(通常のCSVファイルの場合)、インデックスを作成するか、必要な行だけを読むためにファイルを調べる必要があります。ファイルの読み込みを少し速くするには、メモリマップされたファイルを使用することをお勧めします(Boost iostreamsの一部である実装を参照してください:http://www.boost.org/doc/libs/1_39_0/libs/iostreams/doc/classes/mapped_file.html)。

0

他にも述べているように、固定幅の線がない場合は、インデックスを作成せずに行うことはできません。ただし、ファイルの形式を制御している場合は、行番号を格納しておくと、開始行を見つける際にO(サイズ)の代わりに〜O(ログ(サイズ))を取得できます各ライン、すなわちファイルの内容は、次のようなものを見ました:ファイルのこのフォーマットで

1: val1, val2, val3 
2: val4 
3: val5, val6 
4: val7, val8, val9, val10 

を、あなたはすぐにバイナリ検索によって必要なラインを見つけることができます。ファイルの真ん中に求めているで始まります。次の改行まで読み込みます。次に、行を読み、数値を解析します。数値がターゲットより大きい場合は、ファイルの最初の半分でアルゴリズムを繰り返す必要があります。目標の行数よりも小さい場合は、ファイルの後半でそれを繰り返す必要があります。

コーナーケースに注意する必要があります(たとえば、範囲の「開始」と範囲の「終了」が同じ行にあるなど)が、私にとってはこのアプローチは非常に効果的でした過去に日付が入っていたログファイルを解析していました(そして、特定のタイムスタンプの間にある行を見つける必要がありました)。

もちろん、これは明示的に作成されたインデックスまたは固定サイズのレコードのパフォーマンスを上回っていません。

関連する問題