2016-06-25 5 views
1

のような大きなファイルを解析する方法は、ファイル内の総行数が36259190の場合です。各行をオブジェクトに構文解析してリストに保存する方法。Javaで大きなファイルを処理する

私は毎回OutOfMemmoryErrorを取得します。

List<Point> points = new ArrayList<>(); 

public void m2() throws IOException { 
    try (BufferedReader reader = Files.newBufferedReader(Paths.get(DATAFILE))) { 
     reader.lines().map(s -> s.split(",")) 
     .skip(0) 
     .forEach(p -> points.add(newPoint(p[0], p[1], p[2]))); 
    } 
} 


class Point { 
    String X; 
    String Y; 
    String Z; 
} 
+0

Javaにはより大きなヒープがあります。 –

+1

'skip(0)'のポイントは何ですか? – Andreas

+0

私はそれを試みたが、同じ誤りをまだ得ている。コントロールパネルの-Xmx2048mにランタイムパラメータを編集する - java- – Jaray

答えて

1

、Javaへのより多くのメモリを割り当てます。

データベース

メモリが不足している場合は、データベースを使用してください。たとえば、PostgresやH2などです。

データベースの目的の1つは、クエリのメモリを効率的に処理し、必要に応じてデータをロードしながら、データをストレージに保存することです。

データファイルの各行を読むときは、すぐにデータベースに格納してください。後で必要なレコードを照会します。その問合せの結果セットから必要な行のみをメモリー内にインスタンス化します。

+0

もう一つのシングルプロセスオプションはSQLiteです。 –

+0

SQLiteはかなり軽いです。 [その発明者が言ったように](http://use-the-index-luke.com/blog/2014-05/what-i-learned-about-sqlite-at-a-postgresql-conference)、SQLiteは意味する重大なデータベースの中で競合他社と比較してプレーンテキストファイルにデータを保存する代わりに、限られたメモリで3200万行を効率的に処理するために、私はPostgresとおそらくはH2を推奨しますが、SQLiteは推奨しません。 –

+0

SQLiteの能力を過小評価すべきではありません。 8GbのRAMを搭載した4コアi7:36259190は5.7分を挿入します。 1フィールド(X)で80秒間のインデックス作成。インデックスによるクエリ - 1(ミリ秒)。 –

1

コマンドライン引数-Xms(最小メモリ)-Xmx(最大メモリ)を使用する必要があります。

例:四郎による回答が正しい

-Xmx4G (4GB) 
-Xmx200M (200MB) 
java -jar program.jar -Xmx8G 
+0

私に例を教えてもらえますか? – Jaray

+1

そして、「3,600万のオブジェクト」を使ってあなたがしなければならないことを想像するのは難しいです。**: - O **! *毎回何かをするつもりだが、たぶん、私は36のすべての戦略を考えているだろう。200万本*のテキスト行*を配列に格納しますが、オンデマンドでオブジェクト*を作成(破棄)します。 line#* X *のオブジェクトを「ちょうどいい時間に」作成し、オブジェクトをできるだけ早く破棄または再利用します。前述のアプローチが要求する膨大な仮想メモリワーキングセットサイズのため、ほとんどのマシンでは犬のように動作します。 –

+0

自分の投稿を編集して、私の意味を理解できるようにしました。これにより、JVMに最大8GBのRAMが与えられます。 – Shiro

1

データ型には注意が必要です。私はあなたのポイントが3つのテキスト断片ではないと確信しています。したがって、実際のタイプに応じてPointのフィールドを定義します。 intまたはdoubleを使用します。これらの基本データ型は、その表現よりもかなり少ないメモリしか消費しません。

class Point { 
    double x, y, z; 
    Point(double x, double y, double z) { 
     this.x = x; 
     this.y = y; 
     this.z = z; 
    } 
    Point(String x, String y, String z) { 
     this.x = Double.parseDouble(x); 
     this.y = Double.parseDouble(y); 
     this.z = Double.parseDouble(z); 
    } 
} 

するとその後、他の人が述べたように、あなたのJVMに割り当てられたメモリの世話

public List<Point> m2() throws IOException { 
    try(BufferedReader reader = Files.newBufferedReader(Paths.get(DATAFILE))) { 
     return reader.lines().map(s -> s.split(",")) 
      .map(a -> new Point(a[0], a[1], a[2])) 
      .collect(Collectors.toList()); 
    } 
} 

としてデータファイルを収集します。上のポイントクラスを使用すると、問題なく1〜2分のGiBのヒープを使用して36個のMioインスタンスを処理できます。

関連する問題