java execl pio 导出背后的坑

本文探讨了Java导出Excel的两种方法,包括使用较旧的jxl库和Apache POI。针对POI,文章详细说明了在处理大量数据时可能出现的内存泄漏问题,尤其是当数据超过256列或内存限制时。解决方案是利用SXSSFWorkbook类的构造函数,通过指定缓存行数来避免内存溢出。

目前, java导出exexl目前有两种方法,第一种是基于jxl,jar的导出,第二种是基于Apache的pio的方式。

首先,我们先讨论一下execl的格式背景

execl版本最多行最多列
200365536(2^16)256(2^8)
2007(及以上版本)1048576(2^20)16384(2^14)

 

第一步导入所需要的jar包

第一种,jar包较为久远jxl 版本的数据,很可惜这个只支持2003版本的execl

具体数据我本人都是存在Arrylist中,

 

 


		//创建文件,获取数据,写入excel
        // 参数一:数据list
        //参数二:execl的列名,说白了就是一行数据每列的名称,存在数组里面,
        //参数三:输出文件的路径位置
		 public  void writeExcel(List<String[]> list,String[] title,String path) {
			String fileName =path;
			Label label;
			//首先要使用Workbook类的工厂方法创建一个可写入的工作薄(Workbook)对象        
			try {
				WritableWorkbook wwb = Workbook.createWorkbook(new File(fileName));
				File dbfFile = new File(fileName);  
				if (!dbfFile.exists() || dbfFile.isDirectory()) {  
				    dbfFile.createNewFile();  
				}
				int sheets=3;//创建多少个sheet
					//写入数据
				for(int i=0;i<sheets;i++) {
					WritableSheet ws = wwb.createSheet("列表" + (i + 1), i);  //创建一个可写入的工作表
					if(title.length>256){
						System.out.println("......."+title.length);
						System.out.println("加入前"+ws.getColumns());
						ws.insertColumn((title.length-256));
						System.out.println("加入后"+ws.getColumns());
					}
						
					
					//添加表头
					for(int j=0;j<title.length;j++) {
						label = new Label(j, 0, title[j], getHeader());
					
						ws.addCell(label);
					}
					//设置单元格属性
		            WritableCellFormat wc = new WritableCellFormat();
		            // 设置居中
		            wc.setAlignment(Alignment.RIGHT);
		            // 设置边框线
		            wc.setBorder(Border.ALL, BorderLineStyle.THIN);
					int num =(int)(i * maxRow);   
		            int index = 0;
		            for (int m = num; m <list.size(); m++) {  
		                if (index == maxRow) {//判断index == mus的时候跳出当前for循环  
		                    break;  
		                }
		                String[] arrData = list.get(m);
		                for (int k = 0; k < arrData.length; k++) {
		                	ws.setColumnView(k, 20);
		                	//System.out.println("arrData=>"+k+"="+arrData[k]);
		                	//new Label(0, 0, "This is a Label cell",wcfF);
		                	//第一个是代表列数, 第二是代表行数,第三个代表要写入的内容,第四个是可选项,是输入这个label里面的样式 
			                ws.addCell(new Label(k, index+1, arrData[k]));    
		                }
		                index++;
		            }
				}
			        wwb.write();//从内存中写入文件中     
			        System.gc();
		        wwb.close();//关闭资源,释放内存
			} catch (Exception e) {
				e.printStackTrace();
			}  
		}
		//设置表头
		 public static WritableCellFormat getHeader() {
		        // 定义字体
		        WritableFont font = new WritableFont(WritableFont.TIMES, 10,
		                WritableFont.BOLD);
		        try {
		            // 黑色字体
		            font.setColour(jxl.format.Colour.BLACK);
		        } catch (WriteException e1) {
		            e1.printStackTrace();
		        }
		        WritableCellFormat format = new WritableCellFormat(font);
		        try {
		            // 左右居中
		            format.setAlignment(jxl.format.Alignment.CENTRE);
		            // 上下居中
		            format.setVerticalAlignment(jxl.format.VerticalAlignment.CENTRE);
		            // 黑色边框
		            format.setBorder(Border.ALL, BorderLineStyle.THIN, jxl.format.Colour.BLACK);
		            // 黄色背景
		            format.setBackground(jxl.format.Colour.YELLOW);
		        } catch (WriteException e) {
		            e.printStackTrace();
		        }
		        return format;
		    } 
		 

 

 

第二种模式 通过pio模式导出数据,这种里面支持数据库表列数据超过256列

 /// 参数1,数据list
		 /// 参数2 execl头文件数组
		 /// 参数3 execl文件位置
		 
		public void  WriteExeclFilePio(List<String[]> list,String[] title,String path) {
			 try {
				 File dbfFile = new File(path);  
				 if (!dbfFile.exists() || dbfFile.isDirectory()) {  
					 dbfFile.createNewFile();
				 }
			
				 FileOutputStream out = new FileOutputStream(dbfFile);
				 SXSSFWorkbook  wb=new SXSSFWorkbook (); // 定义一个新的工作簿
			
				 SXSSFSheet sheet = wb.createSheet("列表1");

				
				 for (int k = 0; k < list.size(); k++) {
					 SXSSFRow rows=sheet.createRow(k);
					for (int j = 0; j <title.length; j++) {	
						SXSSFCell cell;
						if(k==0){		
							//sheet.trackAllColumnsForAutoSizing();
							cell=rows.createCell(j);					//加载标题数据		
							cell.setCellValue(title[j]);
							
							
						}else{	
							cell=rows.createCell(j);	//加载数据
							cell.setCellValue(list.get(k)[j]);
//							System.out.printf("%S",list.get(k)[j]+"  ");
						}
//						sheet.trackAllColumnsForAutoSizing();
//						sheet.autoSizeColumn(j);
					}
//					System.out.println();
				}
				 sheet.trackAllColumnsForAutoSizing();
				 wb.write(out);
				 out.close();
				 //wb.dispose();
			 	} catch (IOException e) {
			 		e.printStackTrace();
			 	}   
	
}
		

这种可以导出07版及以上execl文件,但是存在一个内存泄漏的问题,由于电脑内存不够,jvm抛出异常,这种是jvm开拓了增加90%的内存,但是内存数据仍然只写了10%,导致虚拟机抛出异常,在查看文档后发现SXSSFWorkbook类中存在一个构造函数SXSSFWorkbook(int rows),这里的参数是表示java虚拟机内心最多缓存多少行数据,当达到这个值的时候,数据就想队列一样往硬盘写数据。

 

pio完整代码:

 /// 参数1,数据list
		 /// 参数2 execl头文件数组
		 /// 参数3 execl文件位置
		 
		public void  WriteExeclFilePio(List<String[]> list,String[] title,String path) {
			 try {
				 File dbfFile = new File(path);  
				 if (!dbfFile.exists() || dbfFile.isDirectory()) {  
					 dbfFile.createNewFile();
				 }
			
				 FileOutputStream out = new FileOutputStream(dbfFile);
				 SXSSFWorkbook  wb=new SXSSFWorkbook (1000); // 定义一个新的工作簿
			
				 SXSSFSheet sheet = wb.createSheet("列表1");

				
				 for (int k = 0; k < list.size(); k++) {
					 SXSSFRow rows=sheet.createRow(k);
					for (int j = 0; j <title.length; j++) {	
						SXSSFCell cell;
						if(k==0){		
							//sheet.trackAllColumnsForAutoSizing();
							cell=rows.createCell(j);					//加载标题数据		
							cell.setCellValue(title[j]);
							
							
						}else{	
							cell=rows.createCell(j);	//加载数据
							cell.setCellValue(list.get(k)[j]);
//							System.out.printf("%S",list.get(k)[j]+"  ");
						}
//						sheet.trackAllColumnsForAutoSizing();
//						sheet.autoSizeColumn(j);
					}
//					System.out.println();
				}
				 sheet.trackAllColumnsForAutoSizing();
				 wb.write(out);
				 out.close();
				 //wb.dispose();
			 	} catch (IOException e) {
			 		e.printStackTrace();
			 	}   
	
}
		

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值