我开发一个Web应用程序,从Excel文件(XLSX)读取数据。 我使用POI读取Excel工作表。 问题是,当我尝试读取Excel文件时,服务器会抛出以下错误:
我想读Excel文件有近80 MB的大小。 任何解决这个问题?
其实用户文件保存到磁盘尝试读取文件后,上传文件和应用程序。 我使用的测试的代码片段是:
File savedFile = new File(file_path);
FileInputStream fis = null;
try {
fis = new FileInputStream(savedFile);
XSSFWorkbook xWorkbook = new XSSFWorkbook(fis);
XSSFSheet xSheet = xWorkbook.getSheetAt(5);
Iterator rows = xSheet.rowIterator();
while (rows.hasNext()) {
XSSFRow row = (XSSFRow) rows.next();
Iterator cells = row.cellIterator();
List data = new ArrayList();
while (cells.hasNext()) {
XSSFCell cell = (XSSFCell) cells.next();
System.out.println(cell.getStringCellValue());
data.add(cell);
}
}
} catch (IOException e) {
e.printStackTrace();
}
有一两件事,会让小的差异是打开开始与文件时。 如果你有一个文件,然后把它传递! 使用一个InputStream需要的一切到内存中,从而消耗了空间的缓冲。 既然你不需要做缓冲,不!
如果你使用最新的运行每晚构建POI的,那么它很容易。 您的代码变为:
File file = new File(file_path);
OPCPackage opcPackage = OPCPackage.open(file);
XSSFWorkbook workbook = new XSSFWorkbook(opcPackage);
否则,它是非常相似的:
File file = new File(file_path);
OPCPackage opcPackage = OPCPackage.open(file.getAbsolutePath());
XSSFWorkbook workbook = new XSSFWorkbook(opcPackage);
这将释放你一点的内存,这可能是不够的。 如果不是,如果你不能增加你的Java堆空间足以应对,那么你就必须停止使用XSSF的usermodel。
除了你一直在使用的电流,友好的usermodel,POI还支持水平较低的方式处理文件。 这种低级别的方法是很难使用,因为你没有周围需要在内存中的整个文件的各种帮手。 但是,它要更多的内存效率,就像你在处理流媒体的方式的文件。 要开始使用,请参阅XSSF和SAX(事件API)如何向一区的POI网站上。 尝试了这一点,也看看不同的例子。
你或许应该改变你的JVM的设置。 尝试添加-Xmx1024 -Xms1024
到发射器。
我认为你必须增加堆的大小。 您可以通过编辑catalina.bat中文件做到这一点。 添加-Xms1024m -Xmx1024m
到CATALINA_OPTS
变量。
- XMS =初始Java堆大小
- XMX =最大Java堆大小
编辑:从catalina.bat中
rem CATALINA_OPTS (Optional) Java runtime options used when the "start", rem "run" or "debug" command is executed. rem Include here and not in JAVA_OPTS all options, that should rem only be used by Tomcat itself, not by the stop process, rem the version command etc. rem Examples are heap size, GC logging, JMX ports etc.
我已经通过实施变革解决了这个问题。 其实首先我是从获取Excel文件和数据的所有数据被存储在ArrayList的类型。 在那之后,我把数据插入到数据库,那是真正的问题。 现在我不是存储数据的。 当我从ResultSet中获得一个记录,我将其插入到数据库立即不是将其存储到数组列表中。 我知道这一个接一个的插入是不是一个好方法,但对于目前我使用这种方法。 在未来,如果我找到更好的一个,我肯定切换到一个。 谢谢大家。
改善你目前的做法可以阅读大约100线(实验用这个数字来获得最佳值 )从Excel和数据库做一个批处理更新。 这将是来得更快。
你也可以有可能在你的代码进行一些优化,移动列表创建了外环的(循环读取行数据)
列表数据=新的ArrayList();
读取在字符串缓冲区中存在的行中的所有单元格的内容(可能以“逗号”分隔),然后将它添加到数组列表“数据”
要添加类型的对象XSSFRow
到ArrayList。 这两者的存储Excel单元格中的整个对象是没有意义的。 取出其内容并丢弃的对象。
后来在插入的内容数据库,然后才能分割分隔单元格的内容并进行插入。
希望这可以帮助!
你最好把它们存储在文件中,并尝试在随后结束加载它们在数据库中。 这将避免单个插入一个