天天看点

POI 读取Excel工具类XSSFWorkbook

<article class="baidu_pl">
	<div id="article_content" class="article_content clearfix csdn-tracking-statistics" data-pid="blog"  data-mod=popu_307  data-dsm = "post" >

							            <div id="content_views" class="markdown_views prism-atom-one-dark">
						<p>近期发现做的excel导出功能会导致内存溢出(推测),于是采用了SXSSFWork控制内存中存放的条数,搞了一个礼拜,碰到了许多问题,通过问题也对POI中的SXSSFWork有了深入的了解。在此做个总结。先上两个官方文档 <br>
           

官网POI中的介绍与实例

SXSSFWorkbook的API文档

public class A{

public String read(){

XSSFWorkbook xssfWorkbook = null;

try {

try {

xssfWorkbook = new XSSFWorkbook(file.getInputStream());

} catch (Exception e) {

logger.error(e.getMessage(), e);

ResponseBean<List> responseBean = new ResponseBean<>();

responseBean.setCode(ResponseBean.FAIL_98);

responseBean.setMsg(“文件上传失败”);

return responseBean;

}

int sheet_numbers = wb.getNumberOfSheets();//获取表的总数

//获取具体哪张表

XSSFSheet sheet = xssfWorkbook.getSheetAt(0);

//获取这张表的行数 (从0开始)

int lastRowNum = sheet.getLastRowNum();

List addBeans = new ArrayList<>();

Subject subject = SecurityUtils.getSubject();

User user = (User) subject.getPrincipal();

for (int i = 1; i <= lastRowNum; i++) {

XSSFRow row = sheet.getRow(i);

if(row == null){

continue;

}

String enterpriseName = getStringCellValue(row.getCell(0));

if(!StringUtils.hasText(enterpriseName)){

continue;

}

String taxNo = getStringCellValue(row.getCell(1));

String linkMan = getStringCellValue(row.getCell(2));

String phoneNo = getStringCellValue(row.getCell(3));

String authCode = getStringCellValue(row.getCell(4));

RegistBindBean addBean=new RegistBindBean();

addBean.setEnterpriseName(enterpriseName);

addBean.setTaxNo(taxNo);

addBean.setLinkMan(linkMan);

addBean.setPhoneNo(phoneNo);

addBean.setUserType(user.getType());

addBean.setUserBussinessNo(user.getBussinessNo());

if(StringUtils.hasText(authCode)){

addBean.setAuthCode(authCode);

addBean.setRegistType(RegistTypeConstant.REGISTBIND);

}else {

addBean.setRegistType(RegistTypeConstant.SLIENT);

}

addBean.setCustomerFrom(CustomerFromConstant.LOCAL);

addBeans.add(addBean);

}

return registBindInterface.incomeBatch(addBeans);

} finally {

IOUtils.closeQuietly(xssfWorkbook);

}

}

private String getStringCellValue(XSSFCell cell) {

String cellValue = “”;

if(cell == null){

return “”;

}

switch (cell.getCellTypeEnum()) {

case STRING:

cellValue = cell.getStringCellValue();

break;

case NUMERIC:

cellValue = new DecimalFormat("#").format(cell.getNumericCellValue());

break;

case BOOLEAN:

cellValue = String.valueOf(cell.getBooleanCellValue());

break;

default:

cellValue = “”;

break;

}

return cellValue;

}

//写

{

FileOutputStream output = new FileOutputStream(new File(xls_write_Address)); //读取的文件路径

SXSSFWorkbook wb = new SXSSFWorkbook(10000);//内存中保留 10000 条数据,以免内存溢出,其余写入 硬盘

for(int sn=0;sn<ls.size();sn++){

Sheet sheet = wb.createSheet(String.valueOf(sn));

wb.setSheetName(sn, sheetnames[sn]);

ArrayList<String[]> ls2 = ls.get(sn);

for(int i=0;i<ls2.size();i++){

Row row = sheet.createRow(i);

String[] s = ls2.get(i);

for(int cols=0;cols<s.length;cols++){

Cell cell = row.createCell(cols);

cell.setCellType(XSSFCell.CELL_TYPE_STRING);//文本格式

sheet.setColumnWidth(cols, s[cols].length()*384); //设置单元格宽度

cell.setCellValue(s[cols]);//写入内容

}

}

}

wb.write(output);

output.close();

}

}

使用时注意一下几点:

1、SXSSF是限制滑动窗口中的行的访问来实现低内存的占用,注意是限制的是访问;

2、滑动窗口的默认大小windowSize为100,是由SXSSFWorkbook.DEFAULT_WINDOW_SIZE定义。

3、可new一个新的SXSSFWorkbook(int windowSize)在工作簿构建时指定窗口大小 ,例如:

SXSSFWorkbook wb = new SXSSFWorkbook(1000);

此时wb的滑动窗口大小为1000;

4、windowSize为-1时,表示可以无限制访问。此种情况下,所有未调用flushRows()刷新的记录都可用于随机访问;

5、SXSSF中的数据达到滑动窗口的限制数量,会产生临时文件且不会自动删除(Win和Linux的默认路径不同),通过调用dispose方法即可删除临时文件:

SXSSFWorkbook wb = new SXSSFWorkbook(100);

//假装有许多操作

wb.dispose();

6、使用createRow()创建新行且未刷新记录的总数超过指定的窗口大小时,具有最低索引值的行将被刷新,并且不能再通过getRow()访问。

比如窗口行数为100,内存当前有100行,createRow()创建一个新行,索引值为0的那一行被刷新到本地文件,该行将无法访问,因为它们已写入磁盘了。(这一点解释了我上一篇由空白行引起的问题,传送门)

目前仅有这一些,后期碰到新的知识点会继续补充。