2017-03-22 3 views
1

私は膨大なファイル(それぞれ4.5GB)を持ち、与えられたトークンで始まる各ファイルの行数を数える必要があります。ファイルごとにトークンが最大200,000回出現することがあります。巨大なファイルの文字列から始まる行を数えるJavaの中で最も速い方法は何ですか

このような巨大なファイルトラバーサルと文字列検出を実現する最速の方法は何でしょうか? ScannerString.startsWith()を使用すると、次の実装より効率的なアプローチがありますか?

public static int countOccurences(File inputFile, String token) throws FileNotFoundException { 
    int counter = 0; 
    try (Scanner scanner = new Scanner(inputFile)) { 
     while (scanner.hasNextLine()) { 
      if (scanner.nextLine().startsWith(token)) { 
       counter++; 
      } 
     } 
    } 
    return counter; 
} 

注:Scannerがボトルネックになっているよう

  • これまでのところ、それは私がトークン検出よりも複雑な処理を追加し、すべての行でそれを適用した場合、すなわち、全体の実行時間が、より以上である(に見えます以下同じ。)あなたの助けを

事前のおかげでハードウェア側に改善の余地がないので、私はSSDを使用してい

  • +1

    共通!それは重複ではない、あなたが参照している質問を読んだことがありますか?私は20kでない何百万ものファイルを持っているファイルについて話しています。トークンの検出についても話しています。あなたは「重複している」タグはあなたが私の質問を読んでいないことを示しているだけで、あなたが指している質問も表示していません。 – Kraal

    +2

    質問が終了したので、答えとして投稿することはできませんが、 'grep' [それは何であるか]を見てください(https://stackoverflow.com/questions/12629749/how-does-grep-run -非常に高速)。これは、[Boyer-Moore検索アルゴリズム](https://en.wikipedia.org/wiki/Boyer%E2%80%93Moore_string_search_algorithm)を使用してすべてのバイトを読み取ることを回避します。 – Malt

    +0

    私はこれも重複しているとは思わない。これはどのようにマークが解除されますか? – mikea

    答えて

    1

    いくつかのポインタ(仮定はラインが比較的短く、データが実際にASCIIまたは類似していることがある):

    • が一度にバイトの巨大なバッファを読んで、(たとえば1/4 GB)不完全な行を切り落として、次の読み込みに先行します。バイトのため

    • 検索、

    • は「で検索パターンを開始することにより、行の先頭を示す文字に変換する時間を無駄にしてはいけない 『\をn』は、特別に最初の行を扱う

    • 高速を使います前処理を犠牲にして検索時間を低減サーチは、実際の行番号(よりむしろ行)が必要な場合、

    • (「速い部分文字列検索」のGoogleの)別の段階で行をカウント

    +0

    これは私がやったことです。詳細については、100MBのバッファとBoyer-Moore検索アルゴリズムを使用した場合、合計実行時間が16分から1分に短縮されました。今のところ、2つに分割されたトークンを検出しなければならないので、近似ですが、最悪の場合でも、探しているオカレンスの0.025%未満を逃してしまいます。ありがとう! – Kraal

    1

    bytestreamで\n<token>を検索することで問題を減らすことができます。その場合、1つの簡単な方法は、ディスクから順次データの塊を読み取ることです(サイズは経験的に決定されますが、開始点は1024ページです)。処理のためにそのデータを別のスレッドに渡します。

    +0

    チャンク境界をまたぐ '\ n 'シーケンスに注意してください。 – florian

    関連する問題