2016-05-27 6 views
3

私は非常に大きな(11GB).jsonファイルを持っています(だと思っていますか?)。Java - オフラインに基づくランダムアクセスファイルからラインを取得

私はJavaファイルIOに非常に精通していないが、私は持っているが、当然のことながら、この記事を見つけました: How to get a random line of a text file in Java?

それが明確に一つ一つを読み方法があまりにも遅いですので、私は受け入れ答えを落としています11GBのファイルの行を選択するだけで約100k行のうちの1つを選択することができます(むしろk)。

利用のRandomAccessFileファイルのランダムなバイト位置をシークする:

幸いなことに、私は私に良く利用のかもしれないと思うことがあっ掲示二の提案があります。

次の行終端記号の左右を検索します。 Lをそれらの間の線とする。確率(MIN_LINE_LENGTH/L.length)で

、そうでない場合はL.を返すこれまでのステップ1.

でとても良いやり直すが、私は「Lは、それらの間のラインもしましょう」という疑問を抱きました。 。私はこの(未テスト)のようなものをやっているだろう

RandomAccessFile raf = ... 
long pos = ... 
String line = getLine(raf,pos); 
... 

どこ

private String getLine(RandomAccessFile raf, long start) throws IOException{ 
    long pos = (start % 2 == 0) ? start : start -1; 

    if(pos == 0) return raf.readLine(); 

    do{ 
     pos -= 2; 
     raf.seek(pos); 
    }while(pos > 0 && raf.readChar() != '\n'); 

    pos = (pos <= 0) ? 0 : pos + 2; 
    raf.seek(pos); 
    return raf.readLine(); 
} 

して、明示的に行の右端を模索する必要性をforgoes line.length()、で操作。

なぜ「次の行終端文字にと右を残すのですか」というのはなぜですか? これらの2つのオフセットからラインを取得するより便利な方法はありますか?

答えて

2

これはほぼ同じように見えます。 - raf.readLine()です。次の行終端記号を探しています。それはあなたのためにやっているだけです。

各バイトは、の下位8ビットのバイトの値を取ることによって文字に変換されます。注意すべき


一つはRandomAccessFile.readLine()ファイルからUnicode文字列を読んでサポートしていないということです文字の上位8ビットを0に設定します。したがって、このメソッドは完全なUnicode文字セットをサポートしません。不正確な読み取りの

デモ:

import java.io.*; 
import java.nio.charset.StandardCharsets; 

class Demo { 
    public static void main(String[] args) throws IOException { 
    try (FileOutputStream fos = new FileOutputStream("output.txt"); 
     OutputStreamWriter osw = new OutputStreamWriter(fos, StandardCharsets.UTF_8); 
     BufferedWriter writer = new BufferedWriter(osw)) { 
     writer.write("ⵉⵎⴰⵣⵉⵖⵏ"); 
    } 

    try (RandomAccessFile raf = new RandomAccessFile("output.txt", "r")) { 
     System.out.println(raf.readLine()); 
    } 
    } 
} 

出力:あなたがしたい場合があり、このよう

$ cat output.txt 
ⵉⵎⴰⵣⵉⵖⵏ 

âµâµâ´°âµ£âµâµâµ 

しかしoutput.txtは正しいデータが含まれていません自分自身を探すか、明示的にc raf.readLine()の結果を正しい文字セットに変換します。

String line = new String(
    raf.readLine().getBytes(StandardCharsets.ISO_8859_1),  
    StandardCharsets.UTF_8); 
+0

ありがとうございます。しかし、 "自分自身を探している"ことは、 '' raf.readLine() ''を実行してから変換することとどう違うのですか?どういうわけか、行の先頭から始まるInputStreamReaderを定義できますか? – User1291

+1

論理的には違いはありません。あなたがそれを自分で行うのであれば、もっと少ない数のオブジェクトを割り当てる必要があります。私は、readline/convertのアプローチから始め、パフォーマンスのボトルネックであることが判明した場合は、後で再訪します。 –

関連する問題