2011-05-09 107 views
1

我有以下两种读取csv文件的实现,所讨论的csv文件并不那么大(5兆字节)。在java中读取小CSV文件导致内存不足错误

第一个实现是使用openCSV,第二个是使用stringTokenizer。

即使我将java max堆内存提升到1G(Xmx),虽然StringTokenizer实现不健壮,但第一个导致内存不足错误,但我没有选择,因为我需要将csv文件读入记忆。

我不明白为什么openCSV版本将消耗如此多的内存给予csv文件(它有200k行,但只有约5m文件大小)的小尺寸。 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; 
} 

回答

0

事实证明,StringTokenizer版本有一个bug,所以两个版本的内存不足。

0

不太可能也许,但我猜想,您输入的数据可能在opencsv库引发的错误,可能导致它陷入循环。

opencsv的下载提供了源代码和库,所以你应该可以自己调试代码。

由于堆栈跟踪没有显示opencsv代码的行号,所以我猜想您需要在构建脚本中更改javac目标以包含“debug = true”,以启用代码的调试编译。

相关问题