Java EXcel工作表POI验证:内存不足错误

Java EXcel工作表POI验证:内存不足错误,java,jdbc,apache-poi,jxl,Java,Jdbc,Apache Poi,Jxl,我试图在将excel文件转储到数据库之前使用java验证它 这是我的代码片段,它会导致错误 try { fis = new FileInputStream(file); wb = new XSSFWorkbook(fis); XSSFSheet sh = wb.getSheet("Sheet1"); for(int i = 0 ; i < 44 ; i++){ XSSFCell a1 = sh.getR

我试图在将excel文件转储到数据库之前使用java验证它

这是我的代码片段,它会导致错误

try {
        fis = new FileInputStream(file);
        wb = new XSSFWorkbook(fis);
        XSSFSheet sh = wb.getSheet("Sheet1");
        for(int i = 0 ; i < 44 ; i++){
            XSSFCell a1 = sh.getRow(1).getCell(i);
            printXSSFCellType(a1);
        }

    } catch (FileNotFoundException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
试试看{
fis=新文件输入流(文件);
wb=新XSSF工作簿(fis);
XSSFSheet sh=wb.getSheet(“Sheet1”);
对于(int i=0;i<44;i++){
XSSFCell a1=sh.getRow(1).getCell(i);
打印XSSFCELLTYPE(a1);
}
}catch(filenotfounde异常){
//TODO自动生成的捕捉块
e、 printStackTrace();
}
捕获(IOE异常){
//TODO自动生成的捕捉块
e、 printStackTrace();
}
这是我得到的错误

Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
    at java.util.ArrayList.<init>(Unknown Source)
    at java.util.ArrayList.<init>(Unknown Source)
    at org.apache.xmlbeans.impl.values.NamespaceContext$NamespaceContextStack.<init>(NamespaceContext.java:78)
    at org.apache.xmlbeans.impl.values.NamespaceContext$NamespaceContextStack.<init>(NamespaceContext.java:75)
    at org.apache.xmlbeans.impl.values.NamespaceContext.getNamespaceContextStack(NamespaceContext.java:98)
    at org.apache.xmlbeans.impl.values.NamespaceContext.push(NamespaceContext.java:106)
    at org.apache.xmlbeans.impl.values.XmlObjectBase.check_dated(XmlObjectBase.java:1273)
    at org.apache.xmlbeans.impl.values.XmlObjectBase.stringValue(XmlObjectBase.java:1484)
    at org.apache.xmlbeans.impl.values.XmlObjectBase.getStringValue(XmlObjectBase.java:1492)
    at org.openxmlformats.schemas.spreadsheetml.x2006.main.impl.CTCellImpl.getR(Unknown Source)
    at org.apache.poi.xssf.usermodel.XSSFCell.<init>(XSSFCell.java:105)
    at org.apache.poi.xssf.usermodel.XSSFRow.<init>(XSSFRow.java:70)
    at org.apache.poi.xssf.usermodel.XSSFSheet.initRows(XSSFSheet.java:179)
    at org.apache.poi.xssf.usermodel.XSSFSheet.read(XSSFSheet.java:143)
    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 com.xls.validate.ExcelValidator.main(ExcelValidator.java:79)
线程“main”java.lang.OutOfMemoryError中的异常:java堆空间 位于java.util.ArrayList。(未知源) 位于java.util.ArrayList。(未知源) 位于org.apache.xmlbeans.impl.values.NamespaceContext$NamespaceContextStack。(NamespaceContext.java:78) 位于org.apache.xmlbeans.impl.values.NamespaceContext$NamespaceContextStack。(NamespaceContext.java:75) 位于org.apache.xmlbeans.impl.values.NamespaceContext.getNamespaceContextStack(NamespaceContext.java:98) 位于org.apache.xmlbeans.impl.values.NamespaceContext.push(NamespaceContext.java:106) 在org.apache.xmlbeans.impl.values.XmlObjectBase.check_日期(XmlObjectBase.java:1273)上 位于org.apache.xmlbeans.impl.values.XmlObjectBase.stringValue(XmlObjectBase.java:1484) 位于org.apache.xmlbeans.impl.values.XmlObjectBase.getStringValue(XmlObjectBase.java:1492) 位于org.openxmlformats.schemas.spreadsheetml.x2006.main.impl.CTCellImpl.getR(未知源) 位于org.apache.poi.xssf.usermodel.XSSFCell.(XSSFCell.java:105) 位于org.apache.poi.xssf.usermodel.XSSFRow.(XSSFRow.java:70) 位于org.apache.poi.xssf.usermodel.XSSFSheet.initRows(XSSFSheet.java:179) 位于org.apache.poi.xssf.usermodel.XSSFSheet.read(XSSFSheet.java:143) 位于org.apache.poi.xssf.usermodel.XSSFSheet.onDocumentRead(XSSFSheet.java:130) 位于org.apache.poi.xssf.usermodel.XSSFWorkbook.onDocumentRead(XSSFWorkbook.java:286) 位于org.apache.poi.POIXMLDocument.load(POIXMLDocument.java:159) 位于org.apache.poi.xssf.usermodel.XSSFWorkbook.(XSSFWorkbook.java:207) 位于com.xls.validate.ExcelValidator.main(ExcelValidator.java:79) 当xlsx文件小于1MB时,这种方法非常有效

我理解这是因为我的xlsx文件大约有5-10MB,POI试图在JVM内存中一次加载整个工作表

可能的解决办法是什么

请帮忙


提前谢谢

好吧,这里有一个链接,其中包含有关错误的详细信息,以及如何修复错误:

好吧,让我试着解释一下你的错误:

java.lang.OutOfMemoryError
有两个变体。一个在Java堆空间中,另一个在PermGen空间中

您的错误可能是由内存泄漏、系统RAM不足或分配给Java虚拟机的RAM很少引起的

Java堆空间和PermGen空间变体之间的区别在于,PermGen空间存储基本类型(如int)上的字符串和数据池,以及如何读取方法和类,Java堆空间的工作方式不同。因此,如果您的项目中有很多字符串或类,并且没有足够的分配/系统RAM,您将得到一个OutOfMemoryError。JVM分配给PermGen的默认RAM量是64 MB,这是相当小的内存空间。链接文章详细解释了此错误,并提供了有关如何修复此错误的详细信息

希望这有帮助

使用


事件API比用户API更新。它面向愿意学习一点低级API结构的中级开发人员。它的使用相对简单,但需要对Excel文件的各个部分有基本的了解(或者愿意学习)。提供的优点是,您可以读取内存占用相对小的XLS。您可以选择两种方法。选项#1-增加JVM堆的大小,以便Java有更多可用内存。使用UserModel代码在POI中处理Excel文件是基于DOM的,因此整个文件(包括解析的表单)需要缓冲到内存中。试着寻求关于如何增加帮助的建议

选项#2,这是更多的工作-切换到基于事件(SAX)的处理。这一次只处理部分文件,因此需要的内存要少得多。然而,它需要您做更多的工作,这就是为什么您最好在这个问题上多投入一些GB内存的原因——内存是便宜的,而程序员不是!有关于如何对.xlsx文件进行SAX解析的说明,您可以查看其中的一些建议


另外,还有一件事——您似乎是通过流加载文件,这是不好的,因为这意味着更多的内容需要缓冲到内存中。请参阅,包括如何直接使用该文件的说明。

在解析xlsx文件时,我也遇到了同样的OOM问题……经过两天的努力,我终于发现下面的代码非常完美

此代码基于sjxlsx。它读取xlsx并存储在HSSF表中

           [code=java] 
            // read the xlsx file
       SimpleXLSXWorkbook = new SimpleXLSXWorkbook(new File("C:/test.xlsx"));

        HSSFWorkbook hsfWorkbook = new HSSFWorkbook();

        org.apache.poi.ss.usermodel.Sheet hsfSheet = hsfWorkbook.createSheet();

        Sheet sheetToRead = workbook.getSheet(0, false);

        SheetRowReader reader = sheetToRead.newReader();
        Cell[] row;
        int rowPos = 0;
        while ((row = reader.readRow()) != null) {
            org.apache.poi.ss.usermodel.Row hfsRow = hsfSheet.createRow(rowPos);
            int cellPos = 0;
            for (Cell cell : row) {
                if(cell != null){
                    org.apache.poi.ss.usermodel.Cell hfsCell = hfsRow.createCell(cellPos);
                    hfsCell.setCellType(org.apache.poi.ss.usermodel.Cell.CELL_TYPE_STRING);
                    hfsCell.setCellValue(cell.getValue());
                }
                cellPos++;
            }
            rowPos++;
        }
        return hsfSheet;[/code]

您可以使用POI中的SXSSF工作簿解决与内存相关的问题。提及

在读取多个CSV并将其合并到单个XLSX文件时,我遇到了类似的问题。 我总共有3张csv表格,每一张有30k行,总计90k行

它通过使用SXSFF解决,如下所示

    public static void mergeCSVsToXLSX(Long jobExecutionId, Map<String, String> csvSheetNameAndFile, String xlsxFile) {
    try (SXSSFWorkbook wb = new SXSSFWorkbook(100);) { // keep 100 rows in memory, exceeding rows will be flushed to
                                                       // disk
      csvSheetNameAndFile.forEach((sheetName, csv) -> {
        try (CSVReader reader = new CSVReader(new FileReader(csv))) {
          wb.setCompressTempFiles(true);
          SXSSFSheet sheet = wb.createSheet(sheetName);
          sheet.setRandomAccessWindowSize(100);

          String[] nextLine;
          int r = 0;
          while ((nextLine = reader.readNext()) != null) {
            Row row = sheet.createRow((short) r++);
            for (int i = 0; i < nextLine.length; i++) {
              Cell cell = row.createCell(i);
              cell.setCellValue(nextLine[i]);
            }
          }
        } catch (IOException ioException) {
          logger.error("Error in reading CSV file {} for jobId {} with exception {}", csv, jobExecutionId,
              ioException.getMessage());
        }
      });

      FileOutputStream out = new FileOutputStream(xlsxFile);
      wb.write(out);
      wb.dispose();
    } catch (IOException ioException) {
      logger.error("Error in creating workbook for jobId {} with exception {}", jobExecutionId,
          ioException.getMessage());
    }
  }
publicstaticvoidmergecsvstoxlsx(长作业执行id,映射csvSheetNameAndFile,字符串xlsxFile){
try(SXSSFWorkbook wb=new-SXSSFWorkbook(100);){//在内存中保留100行,超过的行将刷新到
//圆盘
csvSheetNameAndFile.forEach((sheetName,csv)->{
try(CSVReader reader=new CSVReader(new FileReader(csv))){