我在尝试使用java验证excel文件,然后将其转储到数据库。
这是我的代码段,会导致错误。
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();
}
这是我得到的错误
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)
当xlsx文件小于1 MB时,此功能完全正常。
我理解这是因为我的xlsx文件大约是5-10 MB而且POI尝试在JVM内存中一次加载整个工作表
可能的解决方法是什么?
请帮忙。
提前致谢!
答案 0 :(得分:9)
您有两种选择。选项#1 - 增加JVM堆的大小,以便Java有更多可用内存。使用UserModel代码在POI中处理Excel文件是基于DOM的,因此需要将整个文件(包括已分析的表单)缓冲到内存中。请尝试question like this one获取有关如何增加帮助的建议。
选项#2,更多工作 - 切换到基于事件(SAX)的处理。这一次只处理文件的一部分,因此需要的内存要少得多。但是,它需要你做更多的工作,这就是为什么你可能最好在这个问题上多扔几GB的内存 - 内存很便宜而程序员不是! SpreadSheet howto page有关于如何对.xlsx文件进行SAX解析的说明,有various example files provided by POI可以查看建议。
另外,另一件事 - 您似乎是通过流加载文件,这很糟糕,因为这意味着更多的东西需要缓冲到内存中。请参阅POI Documentation for more on this,包括有关如何直接使用文件的说明。
答案 1 :(得分:1)
事件API比User API更新。它适用于愿意学习一些低级API结构的中间开发人员。它使用起来相对简单,但需要对Excel文件的各个部分有基本的了解(或者愿意学习)。提供的优势是您可以读取相对小内存的XLS。
答案 2 :(得分:0)
嗯,这里有一些链接,其中包含有关您的错误以及如何解决错误的详细信息:http://javarevisited.blogspot.com/2011/09/javalangoutofmemoryerror-permgen-space.html?m=1。
好吧,让我试着解释一下你的错误:
java.lang.OutOfMemoryError
有两种变体。一个在Java Heap Space中,另一个在PermGen Space中。
您的错误可能是由内存泄漏,少量系统RAM或分配给Java虚拟机的RAM很少引起的。
Java Heap Space和PermGen Space变体之间的区别在于PermGen Space在原始类型(如int)上存储字符串和数据池,以及如何读取方法和类,Java堆空间的工作方式不同。因此,如果项目中有很多字符串或类,并且没有足够的分配/系统RAM,则会出现OutOfMemoryError。 JVM分配给PermGen的默认RAM大小为64 MB,这是一小部分内存空间。链接的文章解释了有关此错误的更多信息,并提供了有关如何解决此问题的详细信息。
希望这有帮助!
答案 3 :(得分:-1)
在解析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]