1

csv ファイルを読み取る次の 2 つの実装がありますが、問題の csv ファイルはそれほど大きくありません (5 メガバイト)。

最初の実装は openCSV を使用しており、2 番目の実装は stringTokenizer を使用しています。

StringTokenizer の実装は堅牢ではありませんが、Java の最大ヒープ メモリを 1G(Xmx) に上げてもメモリ不足エラーが発生しましたが、csv ファイルをメモリに読み込む必要があるため、選択の余地がありません。

csvファイルのサイズが小さい(20万行ありますが、ファイルサイズは約5mしかない)ため、openCSVバージョンがなぜそれほど多くのメモリを消費するのかわかりません。そんなに多くのメモリを必要とするopenCSVリーダーは何をしていますか? StringTokenizer バージョンは、すぐに使いこなせます。

openCSV 実装によってスローされるエラーは次のとおりです。

Exception in thread "main" java.lang.OutOfMemoryError: GC overhead limit exceeded
    at java.util.Arrays.copyOfRange(Arrays.java:3209)
    at java.lang.String.<init>(String.java:215)
    at java.lang.StringBuilder.toString(StringBuilder.java:430)
    at au.com.bytecode.opencsv.CSVParser.parseLine(Unknown Source)
    at au.com.bytecode.opencsv.CSVParser.parseLineMulti(Unknown Source)
    at au.com.bytecode.opencsv.CSVReader.readNext(Unknown Source)

private List<String[]> parseCSV(File f) {
    List<String[]>res=new Vector<String[]>();
    CSVReader reader=null;
    try{
        reader = new CSVReader(new BufferedReader(new FileReader(f)));
        String [] nextLine;
        while ((nextLine = reader.readNext()) != null) {
            for(int i=0;i<nextLine.length;i++)if(nextLine[i]!=null)nextLine[i]=nextLine[i].trim();
            res.add(nextLine);
        }

    }catch(IOException exp){
        exp.printStackTrace();
    }finally{
        if(reader!=null)try {
            reader.close();
        } catch (IOException ex) {
            Logger.getLogger(DataStream2.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    return res;

}

 private List<String[]> parseCSV(File f) {
    List<String[]>res=new Vector<String[]>();
    BufferedReader br=null;
    try{
        br = new BufferedReader(new FileReader(f));
        String line =null;
        while((line=br.readLine())!=null){
            StringTokenizer st=new StringTokenizer(",");
            String[]cur=new String[st.countTokens()];
            for(int i=0;i<cur.length;i++){
                cur[i]=st.nextToken().trim();
            }
            res.add(cur);
        }
    }catch(IOException exp){
        exp.printStackTrace();
     }
    finally{
        if(br!=null)try {
            br.close();
        } catch (IOException ex) {
            Logger.getLogger(DataStream2.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    return res;
}
4

3 に答える 3

0

Apache Solrcommons-csvを使用しているので、試してみることをお勧めします。それを使用するSolrは大きな支持です。

于 2011-05-11T10:00:02.060 に答える
0

おそらくそうではありませんが、入力データがopencsvライブラリのバグを引き起こし、ループでスタックする可能性があると思います.

opencsv のダウンロードではソースとライブラリが提供されるため、自分でコードをデバッグできるはずです。

スタック トレースには opencsv コードの行番号が表示されないため、コードのデバッグ コンパイルを有効にするには、ビルド スクリプトの javac ターゲットを変更して「debug=true」を含める必要があると思います。

于 2011-05-09T10:49:00.007 に答える
0

StringTokenizer バージョンにバグがあることが判明したため、両方のバージョンでメモリが不足しています。

于 2011-05-11T09:26:03.077 に答える