2012-02-07 9 views
1

私は任意の数の行を読みたいと思います。ファイルは普通のアスキーテキストファイルです(後でUTF8 /マルチバイト文字ファイルになるかもしれません)巨大なファイルから任意の連続したn行を読み込む方法

だから私が望むのは、特定の行(例えば101〜200)のファイルを読み込む方法です。 (つまり、同じファイルが201-210の別のスレッドによって読み取られ、最初の読み取り操作を待つべきではありません)

読み取る行がない場合は、正常に終了する必要がありますメソッドの出力はリストになる可能性があります。

私が考えていた解決策は、最初にファイル全体を読み込んで、新しい行のそれぞれのバイト位置キャラクター。次に、RandomAccessFileを使用してバイトを読み取り、行に変換します。バイトをStringに変換する必要があります(ただし、読み込みが完了した後に行うことができます)。私は適切な本を保つことによってファイルを越えて読むためのファイル例外の終わりを避けるでしょう。解決策は、ファイルを2回通過するとビット効率が悪くなりますが、ファイルサイズが非常に大きくなる可能性があり、メモリをほとんど保持したくありません。

このようなライブラリがあれば、よりシンプルなネイティブJavaソリューションが素晴らしいでしょう。

いつものように私はあなたの明確化の質問に感謝し、私はこの質問を編集します。

答えて

0

Scannerを使用して、必要な数に達するまでhasNextLine()をループさせてから、必要な数の行を取得してください。実行しても正常に失敗します。そうすれば、あなたはファイルを一度しか読んでいません(スキャナが完全にそれを読まない限り...私は決してフードの下で見たことはありません...しかしあなたが気にしているようには聞こえないので...そこに行く:)

+0

行数を取得するのは簡単ですが、すべての行を繰り返し処理することなく、最初のn行をスキャナでスキップする方法はわかりません。 – geoaxis

+0

私はあなたができるとは言いませんでしたが、私はスキャナがラインインデックスを本当に速く動かすことを望んでいると思いますので、whileループを探してループします:while(myScanner.hasNextLine()&& currentLine ++

0

メモリ消費量を最小限に抑えるには、メモリマップファイルを使用します。これはほとんどヒープを使用しません。メモリに保存されているファイルの量はOSによって処理されるため、動作を自分でチューニングする必要はありません。

2GB以上のファイルがある場合は、複数のマッピングが必要です。最も単純なケースでは、データをスキャンしてすべてのインデックスを覚えることができます。それらのインデックスは、N番目のすべてを覚えているだけなので、多くのスペースを取ることができます。 10分ごとに。

40バイトのラインを持つ2 GBファイルには、400 MBのメモリを必要とする5,000万行が存在する可能性があります。

インデックスを大きくするもう一つの方法は、別のメモリマップファイルを作成することです。

FileChannel fc = new RandomAccessFile(fileName).getChannel(); 
final MappedByteBuffer map2 = fc.map(FileChannel.MapMode.READ_WRITE, 0, fc.size()/10); 

問題は、ファイルを開始する前にどれくらいの大きさにする必要があるのか​​わかりません。幸いにも必要以上に大きくするとメモリやディスクスペースを消費しないので、最も簡単なことはサイズを非常に大きくし、必要なサイズがわかったら切り捨てることです。

これは、ファイルを読み込むたびにファイルを再索引付けするのを避けるためにも使用できます(変更されたときのみ)。ファイルが追加される場合は、毎回ファイルの末尾から索引付けできます。

注:このアプローチを使用すると、多くの仮想メモリを使用できますが、64ビットJVMの場合は、制限が256 TBになる可能性はありません。 32ビットアプリケーションの場合、使用するOSに応じて1.5〜3.5GBに制限されます。

関連する問題