2

大きなファイル (約 5-10Go) を解析し、いくつかの繰り返し文字列の位置 (バイト単位) を可能な限り高速に検索する方法を探しています。

以下のようなことをして、RandomAccessFile リーダーを使用しようとしました。

RandomAccessFile lecteurFichier = new RandomAccessFile(<MyFile>, "r");
while (currentPointeurPosition < lecteurFichier.length()) {
     char currentFileChar = (char) lecteurFichier.readByte();
     // Test each char for matching my string (by appending chars until I found my string)
     // and keep a trace of all found string's position
}

問題は、このコードが遅すぎることです (おそらく、バイトごとに読み取るためですか?)。

私は以下の解決策も試しました。これは速度の点では完璧ですが、文字列の位置を取得できません。

    FileInputStream is = new FileInputStream(fichier.getFile());

    FileChannel f = is.getChannel();

    ByteBuffer buf = ByteBuffer.allocateDirect(64 * 1024);

    Charset charset = Charset.forName("ISO-8859-1");
    CharsetDecoder decoder = charset.newDecoder();

    long len = 0;
    while ((len = f.read(buf)) != -1) {
        buf.flip();

        String data = "";
        try {
            int old_position = buf.position();
            data = decoder.decode(buf).toString();
            // reset buffer's position to its original so it is not altered:
            buf.position(old_position);
        }
        catch (Exception e) {
            e.printStackTrace();
        }

        buf.clear();
    }

    f.close();

誰かが提案するためのより良い解決策を持っていますか?

よろしくお願いします(つづりが間違っていて申し訳ありません、私はフランス語です)

4

2 に答える 2

1

入力データは 8 ビット エンコーディング*でエンコードされているため、ファイルをデコードするのではなく、検索文字列をエンコードすることで検索を高速化できます。

byte[] encoded = searchString.getBytes("ISO-8859-1");

BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
int b;
long pos = -1;
while ((b = bis.read()) != -1) {
    pos++;
    if (encoded[0] == b) {
       // see if rest of string matches
    }
}

ABufferedInputStreamはかなり速いはずです。ByteBuffer を使用すると高速になる可能性がありますが、文字列が一致する可能性があり、バッファー境界にまたがる可能性があるため、検索ロジックがより複雑になります。

次に、この状況に適応できる文字列検索を最適化するさまざまな巧妙な方法があります...バイト/文字の配列ではなく、バイト/文字のストリームを検索する場合。文字列検索に関するウィキペディアのページは、開始するのに適した場所です。

バイト単位で読み取りと照合を行っているため、位置は読み取り (またはスキップ) されたバイト数にすぎないことに注意してください。そのため、ランダム アクセス ファイルを使用する必要はありません。


* 実際、このトリックは多くのマルチバイト エンコーディングでも機能します。

于 2012-11-30T17:56:22.860 に答える
0

「干し草の山」で「針」を検索することは、よく研究されている問題です。StackOverflow 自体の関連リンクを参照してください。説明したアルゴリズムの Java 実装も利用できるはずです。それらのいくつかを試してみて、それらが仕事に合っているかどうかを確認してみませんか?

于 2012-11-30T17:38:16.337 に答える