简体   繁体   English

java.lang.OutOfMemoryError:GC开销限制超出了excel阅读器

[英]java.lang.OutOfMemoryError: GC overhead limit exceeded excel reader

I am getting a java.lang.OutOfMemoryError: GC overhead limit exceeded exception when I try to run the program below. 我得到一个java.lang.OutOfMemoryError:当我尝试运行下面的程序时,GC开销限制超出异常。 This program's main method access' a specified directory and iterates over all the files that contain .xlsx. 该程序的主方法访问'指定目录并迭代包含.xlsx的所有文件。 This works fine as I tested it before any of the other logic. 这工作正常,因为我在任何其他逻辑之前测试它。 And the method it is calling xlsx which basically converts the xlsx file into csv and appends it to an existing file works fine as well. 它调用xlsx的方法基本上将xlsx文件转换为csv并将其附加到现有文件也可以正常工作。 But when I put that in the for loop, this is when I get this exception. 但是当我把它放在for循环中时,这就是我得到这个异常的时候。 I am guessing it there is a conflict when after it has opened the xlsx and converted it the csv and its time to open the second maybe I have to somehow close this line: 我猜它有一个冲突,当它打开xlsx并转换它csv和它的时间打开第二个也许我必须以某种方式关闭这一行:

File inputFile = new File("C:\\Users\\edennis.AD\\Desktop\\test\\"+nameOfFile);

Thats my only guess right now, that it when this file is interfering when the second iteration of the loop comes. 这是我现在唯一的猜测,当这个文件在循环的第二次迭代到来时干扰时。 I am using the Apache POI libraries to manipulate the excel files. 我正在使用Apache POI库来操作excel文件。 Thanks in Advance! 提前致谢!

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

public class ExcelMan {

    public static void main(String[] args) throws FileNotFoundException {



        int i =0;


            File dir = new File("C:\\Users\\edennis.AD\\Desktop\\test\\");
            for (File child : dir.listFiles()) {

            //initializing whether the sheet sent to method is first or not, and //counting iterations for each time the for loop as run

            boolean firstSheet = true;  
            i++;

           String nameOfFile = child.getName();

           if (nameOfFile.contains(".xlsx")){   

            System.out.println(nameOfFile);

                if (i != 0)
                firstSheet = false;


                File inputFile = new File("C:\\Users\\edennis.AD\\Desktop\\test\\"+nameOfFile);

                //  writing excel data to csv 
              File outputFile = new File("C:\\Users\\edennis.AD\\Desktop\\test\\memb.csv");
              xlsx(inputFile, outputFile, firstSheet);


            }


          //  }

        }


    }




        static void xlsx(File inputFile, File outputFile, boolean firstSheet) {
            // For storing data into CSV files
            StringBuffer data = new StringBuffer();


            try {
                FileOutputStream fos = new FileOutputStream(outputFile, true);
                // Get the workbook object for XLSX file
                XSSFWorkbook wBook = new XSSFWorkbook(new FileInputStream(inputFile));
                // Get first sheet from the workbook


                XSSFSheet sheet = wBook.getSheetAt(7);
                Row row;
                Cell cell;
                // Iterate through each rows from first sheet
                java.util.Iterator<Row> rowIterator = sheet.iterator();

                while (rowIterator.hasNext()) {

                    if (firstSheet != true)
                        rowIterator.next();

                    row = rowIterator.next();

                    // For each row, iterate through each columns
                    java.util.Iterator<Cell> cellIterator = row.cellIterator();
                    while (cellIterator.hasNext()) {


                        cell = cellIterator.next();

                        switch (cell.getCellType()) {
                            case Cell.CELL_TYPE_BOOLEAN:
                                data.append(cell.getBooleanCellValue() + "^");

                                break;
                            case Cell.CELL_TYPE_NUMERIC:
                                data.append(cell.getNumericCellValue() + "^");

                                break;
                            case Cell.CELL_TYPE_STRING:
                                data.append(cell.getStringCellValue() + "^");
                                break;                            
                            case Cell.CELL_TYPE_BLANK:
                                data.append("" + "^");
                                break;
                            default:
                                data.append(cell + "^");

                        }


                    }
                    data.append("\r\n");

                }

                fos.write(data.toString().getBytes());
                fos.close();


            } catch (Exception ioe) {
                ioe.printStackTrace();
            }
        }



}

Additional Info: 附加信息:

Below is the stacktrace 下面是堆栈跟踪

   MR.xlsx
    Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
        at org.apache.xmlbeans.impl.store.Cur$CurLoadContext.attr(Cur.java:3039)
        at org.apache.xmlbeans.impl.store.Cur$CurLoadContext.attr(Cur.java:3060)
        at org.apache.xmlbeans.impl.store.Locale$SaxHandler.startElement(Locale.java:3250)
        at org.apache.xmlbeans.impl.piccolo.xml.Piccolo.reportStartTag(Piccolo.java:1082)
        at org.apache.xmlbeans.impl.piccolo.xml.PiccoloLexer.parseAttributesNS(PiccoloLexer.java:1802)
        at org.apache.xmlbeans.impl.piccolo.xml.PiccoloLexer.parseOpenTagNS(PiccoloLexer.java:1521)
        at org.apache.xmlbeans.impl.piccolo.xml.PiccoloLexer.parseTagNS(PiccoloLexer.java:1362)
        at org.apache.xmlbeans.impl.piccolo.xml.PiccoloLexer.parseXMLNS(PiccoloLexer.java:1293)
        at org.apache.xmlbeans.impl.piccolo.xml.PiccoloLexer.parseXML(PiccoloLexer.java:1261)
        at org.apache.xmlbeans.impl.piccolo.xml.PiccoloLexer.yylex(PiccoloLexer.java:4808)
        at org.apache.xmlbeans.impl.piccolo.xml.Piccolo.yylex(Piccolo.java:1290)
        at org.apache.xmlbeans.impl.piccolo.xml.Piccolo.yyparse(Piccolo.java:1400)
        at org.apache.xmlbeans.impl.piccolo.xml.Piccolo.parse(Piccolo.java:714)
        at org.apache.xmlbeans.impl.store.Locale$SaxLoader.load(Locale.java:3439)
        at org.apache.xmlbeans.impl.store.Locale.parseToXmlObject(Locale.java:1270)
        at org.apache.xmlbeans.impl.store.Locale.parseToXmlObject(Locale.java:1257)
        at org.apache.xmlbeans.impl.schema.SchemaTypeLoaderBase.parse(SchemaTypeLoaderBase.java:345)
        at org.openxmlformats.schemas.spreadsheetml.x2006.main.WorksheetDocument$Factory.parse(Unknown Source)
        at org.apache.poi.xssf.usermodel.XSSFSheet.read(XSSFSheet.java:138)
        at org.apache.poi.xssf.usermodel.XSSFSheet.onDocumentRead(XSSFSheet.java:130)
        at org.apache.poi.xssf.usermodel.XSSFWorkbook.onDocumentRead(XSSFWorkbook.java:286)
        at org.apache.poi.POIXMLDocument.load(POIXMLDocument.java:159)
        at org.apache.poi.xssf.usermodel.XSSFWorkbook.<init>(XSSFWorkbook.java:207)
        at ExcelMan.xlsx(ExcelMan.java:71)
        at ExcelMan.main(ExcelMan.java:47)

The excel files are pretty big, there is going to be around 30 or so in the directory and the biggest one is about 170 MB, with these file sizes should I change from POI ? excel文件非常大,目录中大约有30个左右,最大的文件大约是170 MB,这些文件大小应该从POI更改吗?

Whats the size of your excel file? 什么是excel文件的大小? I had a similar problem once, creating csv out of xls . 我有一个类似的问题,用xls创建csv In my case i had to switch to the event driven model , take a look at XSSF and SAX (Event API) . 在我的情况下,我不得不切换到事件驱动模型 ,看看XSSF和SAX(事件API) I too ran out of memory (with -Xmx8g ) 我的内存也耗尽了(使用-Xmx8g

A quote from the linked site: 链接网站的引用:

Further effort on HSSF is going to focus on the following major areas: HSSF的进一步努力将集中在以下主要领域:

  • Performance: POI currently uses a lot of memory for large sheets. 性能:POI目前为大型纸张使用大量内存。

Files do not need to be closed. 文件不需要关闭。 As long as you aren't maintaining references to them they will be GCd as they fall out of scope. 只要您不维护对它们的引用,它们将是GCd,因为它们超出了范围。

The line if (i != 0) will always evaluate to true since you are incrementing the variable i at least once before hitting this conditional. if (i != 0)行将始终评估为true,因为在达到此条件之前,您至少将变量i递增一次。 Thus firstSheet is always set to false. 因此,firstSheet始终设置为false。

The line 这条线

File inputFile = new File("C:\\Users\\edennis.AD\\Desktop\\test\\"+nameOfFile);

is creating new files. 正在创建新文件。 However, you already have a file object for this path represented by child 但是,您已经有一个由child表示的此路径的文件对象

You are always writing to the same file, which you recreate a file object and new FileOutputStream for every time you iterate over the initial directories children even though all the writes are to the same file. 您总是写入同一个文件,即使所有写入都是同一个文件,也会在每次迭代初始目录子项时重新创建文件对象和新的FileOutputStream。

You are not closing your FileOutputStream in a finally block and it may not be properly closing your FileOutputStream under error conditions. 您没有在finally块中关闭FileOutputStream,并且可能无法在错误条件下正确关闭FileOutputStream。

Use StringBuilder instead of StringBuffer unless you need synchronized methods for building the string. 除非需要用于构建字符串的同步方法,否则请使用StringBuilder而不是StringBuffer。

Consider using a FileWriter instead of an intermediary StringBuilder. 考虑使用FileWriter而不是中间StringBuilder。 Instead of writing to a Builder use 而不是写入Builder使用

PrintWriter writer = new PrintWriter(new BufferedWriter(new FileWriter(outputFile, true))))

Instead of doing data.append use writer.print or writer.println Note: PrintWriter and Buffered Writer wrappers aren't strictly necessary, but useful. 而不是使用data.append使用writer.printwriter.println注意:PrintWriter和Buffered Writer包装器不是严格必需的,但是很有用。

If you refer to the XSSFWorkbook javadocs for the constructors options you will see it says "Using an InputStream requires more memory than using a File, so if a File is available then you should instead do something like 'example follows'" http://poi.apache.org/apidocs/org/apache/poi/xssf/usermodel/XSSFWorkbook.html#XSSFWorkbook(java.io.InputStream) 如果您为构造函数选项引用XSSFWorkbook javadocs,您会看到它使用“使用InputStream需要比使用File更多的内存,因此如果文件可用,那么您应该执行类似'example follow'之类的操作” http:// poi.apache.org/apidocs/org/apache/poi/xssf/usermodel/XSSFWorkbook.html#XSSFWorkbook(java.io.InputStream)

Increasing your heap size will likely be a workable solution if all else fails. 如果所有其他方法都失败,增加堆大小可能是一个可行的解决方案。 Assuming you don't have the potential for significantly larger files than what you are currently testing with. 假设您没有比目前正在测试的文件大得多的文件。 Increase heap size in Java 增加Java中的堆大小

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Java PreparedStatement java.lang.OutOfMemoryError:超出了GC开销限制 - Java PreparedStatement java.lang.OutOfMemoryError: GC overhead limit exceeded 詹金斯 java.lang.OutOfMemoryError:超出 GC 开销限制 - Jenkins java.lang.OutOfMemoryError: GC overhead limit exceeded java.lang.OutOfMemoryError:GC开销限制超出了android studio - java.lang.OutOfMemoryError: GC overhead limit exceeded android studio Gridgain:java.lang.OutOfMemoryError:超出了GC开销限制 - Gridgain: java.lang.OutOfMemoryError: GC overhead limit exceeded Spark失败了java.lang.OutOfMemoryError:超出了GC开销限制? - Spark fails with java.lang.OutOfMemoryError: GC overhead limit exceeded? SonarQube java.lang.OutOfMemoryError:超出了GC开销限制 - SonarQube java.lang.OutOfMemoryError: GC overhead limit exceeded Tomcat java.lang.OutOfMemoryError:超出了GC开销限制 - Tomcat java.lang.OutOfMemoryError: GC overhead limit exceeded java.lang.OutOfMemoryError:超出 GC 开销限制 - java.lang.OutOfMemoryError: GC overhead limit exceeded 超出Junit java.lang.OutOfMemoryError GC开销限制 - Junit java.lang.OutOfMemoryError GC overhead limit exceeded 获取错误:java.lang.OutOfMemoryError:超出了GC开销限制 - Getting Error:java.lang.OutOfMemoryError: GC overhead limit exceeded
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM