POI操作Excel2007实例二之“SXSSFWorkbook”处理海量数据
转自:http://blog.csdn.net/little_stars/article/details/8266262
前文讲述了 POI 读取的基本操作,但后期 经过试验,当写入数据量超过5万条以上时,
很容易报错“内存溢出”,就算你调整JVM的xmx为 “2048MB”,也无效果。
后来查资料得知 SXSSFWorkbook 是专门用来处理大量数据写入 Excel2007的问题的。
实例如下,具体步骤神马的,请看前文。
读取仍然是“XSSFWorkbook”,写入则为“SXSSFWorkbook ”。
经试验 写入处理速度在 7000行左右,根据 Excel文件大小 会上下浮动。
Config.java
- package com.excel.poi.gz10000;
- import java.io.BufferedInputStream;
- import java.io.File;
- import java.io.FileInputStream;
- import java.io.FileOutputStream;
- import java.io.IOException;
- import java.io.UnsupportedEncodingException;
- import java.sql.Connection;
- import java.sql.DriverManager;
- import java.sql.ResultSet;
- import java.sql.SQLException;
- import java.sql.Statement;
- import java.text.DecimalFormat;
- import java.text.NumberFormat;
- import java.text.SimpleDateFormat;
- import java.util.ArrayList;
- import java.util.Date;
- import javax.servlet.ServletException;
- import javax.servlet.http.HttpServlet;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- import org.apache.log4j.Logger;
- import org.apache.log4j.PropertyConfigurator;
- import org.apache.poi.ss.usermodel.Cell;
- import org.apache.poi.ss.usermodel.Row;
- import org.apache.poi.ss.usermodel.Sheet;
- import org.apache.poi.xssf.streaming.SXSSFWorkbook;
- import org.apache.poi.xssf.usermodel.XSSFCell;
- import org.apache.poi.xssf.usermodel.XSSFWorkbook;
- /**
- * <b> 数据匹配</b> <br>
- * <ul>
- * <li> 作者:C_Dream </li>
- * <li> 当前版本:4.0 </li>
- * <li> 修改时间: 2012-12-6 17:50 </li>
- * <li> 修改内容:<ol>
- * <li> 更换Excel2007写入方式,大幅提升性能。</li>
- * <li> 引入 log4j,局部提升性能。</li>
- * <li> 部分代码优化,CMD输出提示可选。</li>
- * </ol></li>
- * <li> 创建时间: 2012-11-08 19:22 </li>
- * </ul>
- */
- public class Config extends HttpServlet{
- private static final long serialVersionUID = 1L;
- //Config c = new Config();//此处决不能 new 本类,否则报错:java.lang.StackOverflowError
- String class_path = this.getClass().getResource("").getPath();
- public void doPost(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException
- {
- this.doGet(request,response); //将 表单 post 方法传过来的参数,转给 get方法 去处理
- }
- public void doGet(HttpServletRequest request,HttpServletResponse response)throws ServletException, IOException
- {
- request.setCharacterEncoding("UTF-8"); //转码
- String forms=(String)request.getParameter("forms");
- if(forms.equals("if_3g")){
- try {
- this.read_Excel(request,response);
- } catch (SQLException e) {
- e.printStackTrace();
- } catch (ClassNotFoundException e) {
- e.printStackTrace();
- }
- }
- response.sendRedirect("index.jsp?done=true");
- }
- @SuppressWarnings("rawtypes")
- public void read_Excel(HttpServletRequest request,
- HttpServletResponse response) throws UnsupportedEncodingException, SQLException, ClassNotFoundException {
- PropertyConfigurator.configure(class_path+"log4j.properties");//获取 log4j 配置文件
- Logger logger = Logger.getLogger(Config.class ); //获取log4j的实例
- String startTmie = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
- logger.debug("\n**********【准备处理,正在加载文件】**********");//7
- logger.debug("\n\n**********每行数据间请不要有空行,以免程序误判**********");//7
- logger.debug("\n\n**********由于处理Excel的插件本身性能局限,请控制文件大小,以免影响加载效率。**********");//7
- logger.debug("\n\n**********大小在\t 7 MB \t以内,大约\t 21 万 \t行数据。**********");//7
- logger.debug("\n\n**********本程序每分钟约处理 7000条数据,但根据文件大小会有影响。**********");//7
- request.setCharacterEncoding("UTF-8"); //转码
- String xls_read_Address=(String)request.getParameter("xls_read_Address");//读取
- String xls_write_Address=(String)request.getParameter("xls_write_Address");//写入
- String count_rows=(String)request.getParameter("count_rows");//自动编号
- String tips_cmd=(String)request.getParameter("tips_cmd");//CMD窗口的提示方式
- try {
- DataConvert dc = new DataConvert();//数据转换工具
- DecimalFormat df = (DecimalFormat) NumberFormat.getPercentInstance();
- ArrayList<ArrayList> ls = new ArrayList<ArrayList>();
- File excel_file = new File(xls_read_Address);//读取的文件路径
- FileInputStream input = new FileInputStream(excel_file); //读取的文件路径
- XSSFWorkbook wb = new XSSFWorkbook(new BufferedInputStream(input));
- int sheet_numbers = wb.getNumberOfSheets();//获取表的总数
- logger.debug("\n\n**********共有工作表总数**********:"+sheet_numbers);//7
- String[] sheetnames=new String[sheet_numbers];
- Connection con=null;
- Statement stmt=null;
- ResultSet rs=null;
- String s_3g=null;
- Class.forName("oracle.jdbc.driver.OracleDriver");
- con = DriverManager.getConnection("jdbc:oracle:thin:@12.12.12.123:1521:gz10000","gz12345","12345");
- stmt = con.createStatement();
- for(int i=0;i<sheet_numbers;i++){//遍历所有表
- ArrayList<String[]> ls_a = new ArrayList<String[]>(); //用来存储某个表 读取出来的数据
- Sheet sheet = wb.getSheetAt(i); //获取 某个表
- sheetnames[i] = sheet.getSheetName();//获取表名,存入数组
- logger.debug("\n\n---正在读取和匹配工作表\t《"+sheetnames[i]+"》\t的数据---\n");//7
- int rows_num = sheet.getLastRowNum();//获取行数
- logger.debug("\n\n---表\t《"+sheetnames[i]+"》\t 共有数据---:\t"+rows_num+"\t行");//7
- for( int rows=0;rows<rows_num;rows++){
- Row row = sheet.getRow(rows);//取得某一行 对象
- if(row!=null&&!(row.equals(""))){
- int columns_num = row.getLastCellNum();//获取列数
- String[] s =new String[5];//初始化数组长度
- for( int columns=0;columns<columns_num;columns++){
- Cell cell = row.getCell(columns);
- if(cell!=null){
- switch ( cell.getCellType()) {
- case XSSFCell.CELL_TYPE_STRING: // 字符串
- s[columns] = cell.getStringCellValue();
- if(s[columns]==null){
- s[columns]=" ";
- }
- break;
- case XSSFCell.CELL_TYPE_NUMERIC: // 数字
- double strCell = cell.getNumericCellValue();
- if(String.valueOf(strCell)==null){
- s[columns]=" ";
- }
- df.applyPattern("0");
- s[columns] = df.format(strCell);
- if(Double.parseDouble(s[columns])!=strCell){
- df.applyPattern(Double.toString(strCell));
- s[columns] = df.format(strCell);
- }
- break;
- case XSSFCell.CELL_TYPE_BLANK: // 空值
- s[columns]=" ";
- break;
- default:
- logger.debug("\n---单元格格式不支持---");
- break;
- }
- }
- }
- if(count_rows.equals("是")&&rows>0){
- s[0]=dc.intToString(rows);//自动编号
- }
- /* ******** 访问数据库 ,并判断是否3G ******** */
- String sql="select busiattr1 from ap_t_si_cus_spec_info where cus_phone='"+s[1]+"' and rownum=1";
- rs = stmt.executeQuery(sql);
- if(rs.next()){
- if(rs.getString("busiattr1")!=null){
- s_3g = rs.getString("busiattr1").toString().toUpperCase();
- }
- else{
- s_3g=" ";
- }
- }
- else{
- s_3g=" ";
- }
- /* ******** 访问结束 ******** */
- if(s_3g.contains("3G")){
- s[4]="是";//写入 “是否3G”这一列 的值,比如 “是”
- }
- if(s[4]==null){
- s[4]="\t";
- }
- /* CMD窗口提示方式 */
- if(!(tips_cmd.equals("none"))&&tips_cmd!=null&&!(tips_cmd.equals(""))) {
- if(tips_cmd.equals("all")){
- logger.debug("\n匹配中:"+s[0]+"\t"+s[1]+"\t"+s[2]+"\t"+s[3]+"\t"+ s[4]);
- }else
- if(rows%DataConvert.stringToInt(tips_cmd)==0){
- logger.debug("\n匹配中:"+s[0]+"\t"+s[1]+"\t"+s[2]+"\t"+s[3]+"\t"+ s[4]);
- }
- }
- ls_a.add(s);//添加每行数据到 ls_a
- }
- }
- ls.add(ls_a); //添加 每个表 到 ls
- input.close();
- write_Excel( xls_write_Address, ls, sheetnames ,tips_cmd) ;
- }
- } catch (IOException ex) {
- ex.printStackTrace();
- }
- String endTmie = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
- logger.debug("\n\n***************【处理完成,程序结束】***************");//7
- logger.debug("\n开始时间:"+startTmie);
- logger.debug("\n结束时间:"+endTmie);
- logger.debug("\n新文件输出路径为:"+xls_write_Address);
- }
- @SuppressWarnings({ "rawtypes", "unchecked" })
- public void write_Excel( String xls_write_Address,ArrayList<ArrayList> ls,String[] sheetnames,String tips_cmd ) throws IOException {
- PropertyConfigurator.configure(class_path+"log4j.properties");//获取 log4j 配置文件
- Logger logger = Logger.getLogger(Config.class ); //获取log4j的实例
- 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]);//写入内容
- }
- /* CMD窗口提示方式 */
- if(!(tips_cmd.equals("none"))&&tips_cmd!=null&&!(tips_cmd.equals(""))) {
- if(tips_cmd.equals("all")){
- logger.debug("\n写入中:"+s[0]+"\t"+s[1]+"\t"+s[2]+"\t"+s[3]+"\t"+ s[4]);
- }else
- if(i%DataConvert.stringToInt(tips_cmd)==0){
- logger.debug("\n写入中:"+s[0]+"\t"+s[1]+"\t"+s[2]+"\t"+s[3]+"\t"+ s[4]);
- }
- }
- }
- }
- wb.write(output);
- output.close();
- }
- }
POI操作Excel2007实例二之“SXSSFWorkbook”处理海量数据的更多相关文章
- poi操作excel2007(读取、生成、编辑)
因为现在再写excel2003版的比较low,所以我在这就不介绍了,直接介绍2007,我所用的编程软件是IDEA poi操作office总共有6个jar包,在pom.xml文件中配置如下,也可下载后直 ...
- POI操作Excel(二)
注意:HSSFWorkBook对应2003版Excel XSSFWorkBook对应2007以上的Excel 一.创建时间单元格 public void helloPoi3() throws ...
- java使用Apache POI操作excel文件
官方介绍 HSSF is the POI Project's pure Java implementation of the Excel '97(-2007) file format. XSSF is ...
- poi 操作Excel 以及大数据量导出
maven 依赖 (版本必须一致,否则使用SXSSFworkbook 时程序会报错) <dependency> <groupId>org.apache.poi</grou ...
- POI 的API大全二
1.POI结构与常用类 (1)POI介绍 Apache POI是Apache软件基金会的开源项目,POI提供API给Java程序对Microsoft Office格式档案读和写的功能. .NET的开发 ...
- memcached—Java操作Memcached实例
前面博客介绍了如何在Windows操作系统中安装Memcached,总结一下如何使用Java操作Memcached实例: 代码一: package com.ghj.packageoftool; imp ...
- Java POI操作Excel注意点
excel的行索引和列索引都是从0开始,而行号和列号都是从1开始 POI·操作excel基本上都是使用索引 XSSFRow对象的 row.getLastCellNum() 方法返回的是当前行最后有效列 ...
- Hibernate实例二
Hibernate实例二 一.测试openSession方法和getCurrentSession方法 hebernate中可以通过上述两种方法获取session对象以对数据库进行操作,下面的代码以及注 ...
- Oracle 11g 物理Dataguard日常操作维护(二)
Oracle 11g 物理Dataguard日常操作维护(二) 2017年8月25日 14:34 3.3 3.3.1 查看备库进程状态 SYS(125_7)@fpyj123> select pr ...
随机推荐
- ios AFNetworking 有用篇
在寻常开发中,af是个非常好用的东西.非常喜欢.可是网上的af找了好多都不太全面,不有用.所以我今天做了一个demo.有上传下载的. 比較有用.希望大家可以用到. 去我github下载demo git ...
- java设计模式---享元模式
享元模式 顾名思义:共享元对象.如果在一个系统中存在多个相同的对象,那么只需要共享一份对象的拷贝,而不必为每一次使用创建新的对象. 享元模式是为数不多的.只为提升系统性能而生的设计模式.它的主要作用就 ...
- 作为iOS开发者不得不follow的52人
对于每位iOS开发者来说,Twitter是个获得最新iOS开发技术和相关信息的好地方.如果你刚好有Twitter账户,可以关注以下为你推荐的该领域内的52个优秀人物. 1.Tim Cook 这位无需多 ...
- ASP.NET-FineUI开发实践-10
嵌套Grid,光棍月大放送,不藏着掖着.实在写的不好,没脸藏啊~只考虑显示排序修改什么的都不管! 话说三石官网加实例了,http://fineui.com/demo/#/demo/grid/grid_ ...
- 传入字典的模型项的类型为“System.Data.Entity.DynamicProxies.
今天做东西遇到了,这样的一个问题,最后了半天才找到问题所在,现在给大家分享一下问题所在: 传入字典的模型项的类型为“System.Data.Entity.DynamicProxies.doctorUs ...
- 基于jQuery仿uploadify的HTML5图片上传控件jquery.html5uploader
(function($){ var methods = { init:function(options){ return this.each(function(){ var $this = $(thi ...
- 关于数据库中varchar/nvarchar类型数据的获取注意事项
当在页面后台获取数据库表中某字段的数据时,需注意该数据的类型.防止因实际数据的字符长度因达不到指定数据类型规定的字符长度而导致空格的占位符. 比如: MSSQL中某一表的结构如下: 表中的数据: ...
- start with connect by prior学习
这是oracle中的树查询,查询出来的数据会根据上下级组成树的结构.select * from mw_sys.mwt_pd_deps start with obj_id = '63EBEC8E-E76 ...
- R1:创建Libevent库
原文链接:http://www.wangafu.net/~nickm/libevent-book/Ref1_libsetup.html Setting up the Libevent library ...
- 关于C++条件运算符(三目运算符)右结合的说明
C++条件运算符 a ? c : d;是右结合的,但是这个右结合要怎么理解呢? 对于a ? b : c ? d : e; 这样的表达式如果按照右结合来解读的话,那不应该是先运算c,然后返回d或者e,返 ...