アプリ版:「スタンプのみでお礼する」機能のリリースについて

10000行1GBほどの大容量のテキストファイルの内容を解析しようとしています。

このテキストファイルは約20行で一塊のデータが入っており、次の20行からまた一塊のデータがはいっています。現在、全行を1行ごとにArrayListに格納してから 各行にキーワードが含まれていないかチェックし、含まれていたらそのデータの塊の中にある2行目を行を出力しようとしています。

しかし、10000行のArrayListを宣言しようとしたところ、途中でOutOfMemoryになり、メモリ不足になります。そこで、最初の20行を読み込み、処理をし、次の20行を読み込み処理をする・・・と考えているのですが、このようなことをJAVAのソースコードで実現することは可能でしょうか??

皆さんは大容量ファイルを解析するときにどのような手法をとっていますか?

ご教示いただければ幸いです。

A 回答 (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行目が無かった";
}
}
    • good
    • 0
この回答へのお礼

なるほど!Listに入れなくてはいけないというのは自分の固定観念でした!
たしかにそもそもListに入れる必要はなさそうですね!

ありがとうございます。

ベストアンサーとして選ばさせていただきます。

お礼日時:2011/12/18 22:08

これ, 「データの塊」ごとに処理すればいいだけじゃないでしょうか? もしそうなら


「1つの『データの塊』を読み込むメソッド」
を作るのが簡単だと思う.
    • good
    • 0

具体的な例を出したほうが、誤解などが少なくなると思います

    • good
    • 0

ぱっと考えつくのは



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 …

利用したら? 2GBの壁にきをつければ。。。
    • good
    • 0

20行ワンセットが約束されてるなら。



grepかfindで、キーワードを含む行番号を取得して考える。

この回答への補足

すみません。言葉不足でした。
20行が必ずワンセットになっているとは限りません。ただ、30行の中には必ず収まっていることと、
データとデータの塊の境目に必ず”区切りキーワード”がくることがわかっています。

補足日時:2011/12/14 22:55
    • good
    • 0

そりゃぁ「最初の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(" キーワード ")){

           //キーワードが見つかったときに、ここに処理を書く。
}
}

補足日時:2011/12/14 22:50
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!