天天看點

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的那一行被重新整理到本地檔案,該行将無法通路,因為它們已寫入磁盤了。(這一點解釋了我上一篇由空白行引起的問題,傳送門)

目前僅有這一些,後期碰到新的知識點會繼續補充。