- ベストアンサー
大容量テキストファイルの内容解析について
- 10000行1GBほどの大容量のテキストファイルの内容を解析しようとしています。メモリ不足を解消するため、20行ごとに処理を行う方法を検討しています。
- 現在、全行を1行ごとにArrayListに格納してからキーワードのチェックを行っていますが、途中でOutOfMemoryになる問題が発生しています。
- そのため、20行ごとにデータを読み込み、処理を行う方法を検討しています。皆さんはどのような手法を使用しているのか教えていただけると助かります。
- みんなの回答 (6)
- 専門家の回答
質問者が選んだベストアンサー
そもそもListに入れる必要が無いと思います。 ・2行目は覚えておく ・"区切りキーワード"を見つけるまで、1行ずつキーワードが含まれているかチェックする。 ・"区切りキーワード"を見つけるか、最後まで読み込んだ時に、直前のブロックにキーワードが 含まれていたら、覚えておいた2行目を出力する。 String secondLine = "2行目が無かった"; String line = br.readLine(); while (line != null) { // 全体が終わるまでループ it cnt = 1; // 処理行数(ブロック内の) boolean isFound = false; // キーワード発見フラグ while (line != null) { // 全体が終わるまでループ(区切りキーワードが見つかったらbreak)) if (line.contains(Sep)) { break; // 区切りキーワード発見 } if (cnt == 2) { secondLine = line; // 出力用の2行目を退避 } if (!isFound && line.contains(keyword)) { isFound = true; // キーワード発見 } line = br.readLine(); // 次行読み込み cnt++; } if (isFound) { System.out,println(secondLine); secondLine = "2行目が無かった"; } }
その他の回答 (5)
- Tacosan
- ベストアンサー率23% (3656/15482)
これ, 「データの塊」ごとに処理すればいいだけじゃないでしょうか? もしそうなら 「1つの『データの塊』を読み込むメソッド」 を作るのが簡単だと思う.
- ngsvx
- ベストアンサー率49% (157/315)
具体的な例を出したほうが、誤解などが少なくなると思います
ぱっと考えつくのは BufferedReader in = getReader(); List<String> lines = new ArrayList<String>(); String line; System.out.println("----------------------"); while (in.ready()) { line = in.readLine(); lines.add(line); if (lines.size() == 3) { for (String l : lines) { if (l.indexOf("15") >= 0) { System.out.println(lines.get(1)); } } lines.clear(); } } System.out.println("----------------------"); だがこれも OutOfMemory でるから。 http://java.sun.com/javase/ja/6/docs/ja/api/java/io/RandomAccessFile.html 利用したら? 2GBの壁にきをつければ。。。
- bin-chan
- ベストアンサー率33% (1403/4213)
20行ワンセットが約束されてるなら。 grepかfindで、キーワードを含む行番号を取得して考える。
補足
すみません。言葉不足でした。 20行が必ずワンセットになっているとは限りません。ただ、30行の中には必ず収まっていることと、 データとデータの塊の境目に必ず”区切りキーワード”がくることがわかっています。
- Tacosan
- ベストアンサー率23% (3656/15482)
そりゃぁ「最初の20行を読み込み、処理をし、次の20行を読み込み処理をする」のは可能です. とりあえず「最初の 20行を読み込む」ところだけ書いてみてください.
補足
補足します。実際のデータは必ず20行が約束されているわけではありませんが、30行までにはひとつのデータの塊が収まることがわかっています。そして、データとデータの境には”区切りキーワード”が必ずあることがわかっています。 そこで以下のように最初の30行を”区切りキーワード”が来るまでArrayListに格納し、処理をするところのプログラムです。 ここから先が不明なのは 1.前回読み込んだ行までを覚えて、 2.その行をスタート位置とし、 3.そこから次の30行を読み、同じ処理を繰り返す。 の部分です・・・・。 public static void main(String[] args){ ArrayList<String> copy=new ArrayList<String>();//1行ずつ格納 String Sep = "区切りキーワード";//30行以内には必ず1回はこの区切りキーワードが来ます。 try { br = new BufferedReader(new InputStreamReader (new FileInputStream("C:\\sample\test.txt"), "Shift_JIS")); while(i<30){ //”区切りキーワードが来るまでループ” line= br.readLine(); copy.add(i, line); i++; if(line.contains(Sep)){ break; } } for(int k=0;k<copy.size();k++){ //Arraylistに収めた中で処理をする(キーワード検索) if(copy.get(k).contains(" キーワード ")){ //キーワードが見つかったときに、ここに処理を書く。 } }
お礼
なるほど!Listに入れなくてはいけないというのは自分の固定観念でした! たしかにそもそもListに入れる必要はなさそうですね! ありがとうございます。 ベストアンサーとして選ばさせていただきます。