文件读取:内存不足错误

时间:2014-12-24 17:23:09

标签: java filereader opencsv

我需要浏览大约3000个文件夹,每个文件夹包含300个CSV文件。

这是((nextLine=csvReader.readNext()) != null)时行发生的错误:

Exception in thread "main" java.lang.OutOfMemoryError: GC overhead limit exceeded
    at au.com.bytecode.opencsv.CSVParser.parseLine(CSVParser.java:206)
    at au.com.bytecode.opencsv.CSVParser.parseLineMulti(CSVParser.java:174)
    at au.com.bytecode.opencsv.CSVReader.readNext(CSVReader.java:237)
    at DA.readTelemetryData(DA.java:78)
    at DA.main(DA.java:24)

问题是如何解决这个问题?为什么会出现问题?我的代码出了什么问题?

我在这里提供代码:

private static HashMap<Integer,HashMap<Integer,List<double[]>>> readTelemetryData() throws Exception
    {
        HashMap<Integer,HashMap<Integer,List<double[]>>> xy_total = new HashMap<Integer,HashMap<Integer,List<double[]>>>(); 

        for (int i=0; i<Constants.MAX_FOLDERS; i++)
        {
            HashMap<Integer,List<double[]>> xy_total_per_folder= new HashMap<Integer,List<double[]>>();
            for (int j=0; j<Constants.MAX_FILES_INSIDE_FOLDER; j++)
            {               
                CSVReader csvReader = null;
                File f = new File("data/"+ (i+1) +"/"+ (j+1) +".csv");
                if(f.exists())
                {
                    csvReader = new CSVReader(new FileReader(f));
                    List<double[]> xyArr = new ArrayList<double[]>();
                    String[] firstLine=csvReader.readNext();
                    if (firstLine != null) 
                    {
                      String[] nextLine=null;
                      while ((nextLine=csvReader.readNext()) != null) 
                      {
                          double[] d = new double[2];
                          d[0]=Double.parseDouble(nextLine[0]);
                          d[1]=Double.parseDouble(nextLine[1]);
                          xyArr.add(d);
                      }
                    }

                    xy_total_per_folder.put(j, xyArr);

                    csvReader.close();
                }
            }
            xy_total.put(i, xy_total_per_folder);
        }
        return xy_total;
    }

2 个答案:

答案 0 :(得分:2)

你的内存不足。

HashMap<Integer,V>是一个相当糟糕的选择。密钥需要16个字节,每个+死区的条目可能需要24个字节。您的double[]则需要32个字节(用于存储16个字节的有效负载)。在数组列表中,您需要另外4个字节作为参考...

因此,例如,每行将花费您36个字节的16个实例。

考虑使用更紧凑的数据结构。 GNU Trove是一个为原始类型提供优秀集合的库;但是不要低估数组的价值......

用于处理大量原始类型(intdouble等)远离java.util.集合。相反,花些额外的时间来组织你的记忆。

例如,您可以使用Trove的TDoubleArrayList,一个用于所有 x,一个用于所有 y值,而不是使用每行一个数组。读完文件后,可以将它们转换为最小double[] x; double[] y;数组,并重用TDoubleArrayList来解析下一个文件。

最后但并非最不重要的是,Java默认只使用25%的内存。使用-Xmx来增加限制。

运行内存探查器。大部分内存分配在哪里?所有这些都需要吗?也许你正在使用的CSVReader有内存泄漏!使用内存分析器是一种简单的方法。

但是算一算。你有几行 - 可以你把所有这些都放到内存中吗?

答案 1 :(得分:0)

这种行为通常有两个原因:

  1. 内存泄漏。这意味着您可以编写不再需要的商店数据。分析内存转储以进行修复。

  2. 内存不足,因为你的程序实际上需要那么多内存。哟可以简单地给它更多的记忆。或者尝试更改算法和数据结构。