使用Workbook读取表格问题总结
- 一、Workbook类型
- 二、问题总结
- 1.SXSSFWorkbook为什么我Create了一万行Row但是却获取不到?
- 2.读取表格
一、Workbook类型
Workbook分三种类型:
1.HSSFWorkbook 用于Excel2003版及更早版本(扩展名为.xls)的导出;
2.XSSFWorkbook 用于Excel2007版(扩展名为.xlsx)的导出;
3.SXSSFWorkbook:相对前面两种,会在导出数据达到万以上的数据,会报内存不足,导致失败的问题。这时就要用到sxssf,来导出较大数据量
注:
HSSFWorkbook和XSSFWorkbook的Excel Sheet导出条数上限(<=2003版)是65535行、256列,(>=2007版)是1048576行,16384列,如果数据量超过了此上限,那么可以使用SXSSFWorkbook来导出。实际上上万条数据,甚至上千条数据就可以考虑使用SXSSFWorkbook了。
经测试,同样向表格中写入50w条数据,使用SXSSFWorkbook向Excel中写入50万条数据,只需要34秒左右,内存占用率最多在700M左右,CPU使用率在25%左右;使用XSSFWorkbook内存占用率最多在2.1个G左右(占用了很大的内存),CPU使用率在90%左右,最后内存溢出了。。。
二、问题总结
1.SXSSFWorkbook为什么我Create了一万行Row但是却获取不到?
这时要注意到SXSSFWorkbook的构造函数中的rowAccessWindowSize
这个参数,会指定一个sheet可读取的row数目,超过该数目的row,会被写入到磁盘文件中,进而不能在通过getRow访问到,通过这种方式,内存使用空间就缩小很多了。
需要注意的是,如果该值指定为-1,说明不限制行数,所有记录都写入内存中;该值不能取0,因为这意味着任何新row都会写入磁盘,进而不能访问
2.读取表格
读取表格时先要用XSSFWorkbook加载,再用SXSSFWorkbook 构造,代码如下(示例):
InputStream fis = new FileInputStream(file);
XSSFWorkbook xssfWorkbook = new XSSFWorkbook(fis);
SXSSFWorkbook workbook = new SXSSFWorkbook(xssfWorkbook, -1);
而且读取内容、行数等时要先调用getXSSFWorkbook。因为所有的初始模板记录存在于XSSFWorkbook中,需要用sxssfWorkbook.getXSSFWorkbook()方法去获取初始模板的行数据。这也可以解释为什么其构造函数中有XSSFWorkbook了。例如下面获取sheet页行数的方法:
/**
* 返回sheet 中的行数
*
* @param sheetIx 指定 Sheet 页,从 0 开始
* @return
*/
public int getRowCount(int sheetIx)
{
//xlsx格式。将SXSSFWorkbook转成XSSFWorkbook,再获取XSSFSheet
if (isXlsx)
{
XSSFSheet sheet = ((SXSSFWorkbook) workbook).getXSSFWorkbook().getSheetAt(sheetIx);
return sheet.getPhysicalNumberOfRows();
}
//xls格式,直接读取
else
{
Sheet sheet = workbook.getSheetAt(sheetIx);
return sheet.getPhysicalNumberOfRows();
}
}