POI 读取excel 内存溢出

决战屁屁虾 2018-06-11 03:30:20
环境:jdk 1.5
分批读取,还是溢出,求解
注:不要用事件模式,不要调整内存
附上代码


package ttt;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;

import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;


/**
* 分批读取提交
*
*/
public class TT4 {
XSSFSheet xssfSheet =null;//Sheet 对象
ArrayList<ArrayList<String>> ans = new ArrayList<ArrayList<String>>();
ArrayList<ArrayList<String>> arr = null;

/**
* 初始化Sheet
*/
public TT4(){
XSSFWorkbook xssfWorkbook = null;
File excelFile = new File("D:\\work\\workWord\\资料\\案例\\","template.xlsx");
InputStream is;
try {
is = new FileInputStream(excelFile);
xssfWorkbook = new XSSFWorkbook(is);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
xssfSheet = xssfWorkbook.getSheetAt(0);
}

public static void main(String[] args) throws IOException {


new TT4().test();


}

/**
* 分批测试
* @throws IOException
*/
public void test() throws IOException{
int lastRowNum = xssfSheet.getLastRowNum();
int excecuteNum = this.testRowNumber(lastRowNum);

for(int i = 0 ;i < excecuteNum; i++){
switch (i){
case 1:
this.printOut(3,1000);
break;
case 2:
this.printOut(1001,2000);
break;
case 3:
this.printOut(2001,3000);
break;
case 4:
this.printOut(3001,4000);
break;
case 5:
this.printOut(4001,5000);
break;
case 6:
this.printOut(5001,6000);
break;
}
}
}


/**
* 打印输出
* @param beginRow
* @param endRow
* @throws IOException
*/
public void printOut(int beginRow,int endRow) throws IOException{
arr=this.xlsx_reader(0,beginRow,endRow,0,8);
ArrayList<String> row = null;
for(int i=0;i<arr.size();i++){
row=arr.get(i);
for(int j=0;j<row.size();j++){
System.out.print(row.get(j)+" ");
}
System.out.println("");
}
ans.clear();
arr.clear();
}

/**xlsx文件读取函数
* @param sheetNumArg 第几个Sheet
* @param rowNumBegin 开始行
* @param rowNumEnd 结束行
* @param columnBegin 开始列
* @param columnEnd 结束列
* @return
* @throws IOException
*/
public ArrayList<ArrayList<String>> xlsx_reader(int sheetNumArg,
int rowNumBegin, int rowNumEnd, int columnBegin, int columnEnd)
throws IOException {

if (xssfSheet == null) {
return null;
}

// 对于每个sheet,读取其中的每一行
for (int rowNum = rowNumBegin; rowNum <= rowNumEnd; rowNum++) {
XSSFRow xssfRow = xssfSheet.getRow(rowNum);
if (xssfRow == null) {
continue;
}
ArrayList<String> curarr = new ArrayList<String>();
for (int columnNum = columnBegin; columnNum < columnEnd; columnNum++) {
XSSFCell cell = xssfRow.getCell(columnNum);
curarr.add(Trim_str(getValue(cell)));
}
ans.add(curarr);
curarr = null;
}
return ans;
}

//判断后缀为xlsx的excel文件的数据类
@SuppressWarnings({"static-access" })
private static String getValue(XSSFCell xssfRow) {
if(xssfRow==null){
return "";
}
if (xssfRow.getCellType() == xssfRow.CELL_TYPE_BOOLEAN) {
return String.valueOf(xssfRow.getBooleanCellValue());

} else if (xssfRow.getCellType() == xssfRow.CELL_TYPE_NUMERIC) {
double cur=xssfRow.getNumericCellValue();
long longVal = Math.round(cur);
Object inputValue = null;
if(Double.parseDouble(longVal + ".0") == cur)
inputValue = longVal;
else
inputValue = cur;
return String.valueOf(inputValue);

} else if(xssfRow.getCellType() == xssfRow.CELL_TYPE_BLANK || xssfRow.getCellType() == xssfRow.CELL_TYPE_ERROR){
return "";
}

else {
return String.valueOf(xssfRow.getStringCellValue());
}
}


//字符串修剪 去除所有空白符号 , 问号 , 中文空格
static private String Trim_str(String str) {
if (str == null)
return null;
return str.replaceAll("[\\s\\?]", "").replace(" ", "");
}

/**
* 根据总行数,判断读几次
* 一千行一次
*/
public int testRowNumber(int i){
if(0 == i){
return 0;
}
if(i<1000){
return 1;
}else{
return i / 1000 +1;
}
}

}

...全文
1032 6 打赏 收藏 转发到动态 举报
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
花木兰1闪21A 2018-08-28
  • 打赏
  • 举报
回复
文件太大就用csv 了
stacksoverflow 2018-06-11
  • 打赏
  • 举报
回复
引用 4 楼 weixin_33654636 的回复:
[quote=引用 1 楼 stacksoverflow 的回复:] 参照 http://www.cnblogs.com/resentment/p/6367404.html
谢谢回答! 附的代码是POI的用户模式读取的,你说的哪个应该就是事件模式的,事件模式速度非常快,也不会溢出,但是它读数据的时候会忽略掉空的单元格,直接跳到下个有值的单元格[/quote] 我不能重现你的问题,所以只能试着给你方案。 1.ans和arr都是类变量,变成局部变量试一下。 2.我看到你用的list.clear方法来释放存储空间,没有仔细研究,如果list本身本撑大到一定程度的话,clear是否能迅速释放空间?还是每次new一个list在局部变量,方法栈退出后自然没有引用。
决战屁屁虾 2018-06-11
  • 打赏
  • 举报
回复
引用 1 楼 stacksoverflow 的回复:
参照 http://www.cnblogs.com/resentment/p/6367404.html
谢谢回答! 附的代码是POI的用户模式读取的,你说的哪个应该就是事件模式的,事件模式速度非常快,也不会溢出,但是它读数据的时候会忽略掉空的单元格,直接跳到下个有值的单元格
决战屁屁虾 2018-06-11
  • 打赏
  • 举报
回复
引用 2 楼 stacksoverflow 的回复:
在你分批前就已经溢出了,所以不要费力气在分批上,把excel拆成小的或者采用流方式读取。
输出到4000行的时候才报的溢出,不是一开始就报溢出
stacksoverflow 2018-06-11
  • 打赏
  • 举报
回复
在你分批前就已经溢出了,所以不要费力气在分批上,把excel拆成小的或者采用流方式读取。
stacksoverflow 2018-06-11
  • 打赏
  • 举报
回复
参照 http://www.cnblogs.com/resentment/p/6367404.html

62,614

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧