转自:http://blog.csdn.net/little_stars/article/details/8266262

前文讲述了 POI 读取的基本操作,但后期 经过试验,当写入数据量超过5万条以上时,

很容易报错“内存溢出”,就算你调整JVM的xmx为 “2048MB”,也无效果。

后来查资料得知 SXSSFWorkbook 是专门用来处理大量数据写入 Excel2007的问题的。

实例如下,具体步骤神马的,请看前文。

读取仍然是“XSSFWorkbook”,写入则为“SXSSFWorkbook ”。

经试验 写入处理速度在 7000行左右,根据 Excel文件大小 会上下浮动。

Config.java

    1. package com.excel.poi.gz10000;
    2. import java.io.BufferedInputStream;
    3. import java.io.File;
    4. import java.io.FileInputStream;
    5. import java.io.FileOutputStream;
    6. import java.io.IOException;
    7. import java.io.UnsupportedEncodingException;
    8. import java.sql.Connection;
    9. import java.sql.DriverManager;
    10. import java.sql.ResultSet;
    11. import java.sql.SQLException;
    12. import java.sql.Statement;
    13. import java.text.DecimalFormat;
    14. import java.text.NumberFormat;
    15. import java.text.SimpleDateFormat;
    16. import java.util.ArrayList;
    17. import java.util.Date;
    18. import javax.servlet.ServletException;
    19. import javax.servlet.http.HttpServlet;
    20. import javax.servlet.http.HttpServletRequest;
    21. import javax.servlet.http.HttpServletResponse;
    22. import org.apache.log4j.Logger;
    23. import org.apache.log4j.PropertyConfigurator;
    24. import org.apache.poi.ss.usermodel.Cell;
    25. import org.apache.poi.ss.usermodel.Row;
    26. import org.apache.poi.ss.usermodel.Sheet;
    27. import org.apache.poi.xssf.streaming.SXSSFWorkbook;
    28. import org.apache.poi.xssf.usermodel.XSSFCell;
    29. import org.apache.poi.xssf.usermodel.XSSFWorkbook;
    30. /**
    31. * <b> 数据匹配</b> <br>
    32. * <ul>
    33. * <li> 作者:C_Dream </li>
    34. * <li> 当前版本:4.0 </li>
    35. * <li> 修改时间: 2012-12-6 17:50 </li>
    36. * <li> 修改内容:<ol>
    37. * <li> 更换Excel2007写入方式,大幅提升性能。</li>
    38. * <li> 引入 log4j,局部提升性能。</li>
    39. * <li> 部分代码优化,CMD输出提示可选。</li>
    40. * </ol></li>
    41. * <li> 创建时间: 2012-11-08 19:22 </li>
    42. * </ul>
    43. */
    44. public class Config extends HttpServlet{
    45. private static final long serialVersionUID = 1L;
    46. //Config c = new Config();//此处决不能 new 本类,否则报错:java.lang.StackOverflowError
    47. String class_path = this.getClass().getResource("").getPath();
    48. public void doPost(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException
    49. {
    50. this.doGet(request,response); //将 表单  post 方法传过来的参数,转给 get方法 去处理
    51. }
    52. public void doGet(HttpServletRequest request,HttpServletResponse response)throws ServletException, IOException
    53. {
    54. request.setCharacterEncoding("UTF-8"); //转码
    55. String forms=(String)request.getParameter("forms");
    56. if(forms.equals("if_3g")){
    57. try {
    58. this.read_Excel(request,response);
    59. } catch (SQLException e) {
    60. e.printStackTrace();
    61. } catch (ClassNotFoundException e) {
    62. e.printStackTrace();
    63. }
    64. }
    65. response.sendRedirect("index.jsp?done=true");
    66. }
    67. @SuppressWarnings("rawtypes")
    68. public void read_Excel(HttpServletRequest request,
    69. HttpServletResponse response) throws UnsupportedEncodingException, SQLException, ClassNotFoundException  {
    70. PropertyConfigurator.configure(class_path+"log4j.properties");//获取 log4j 配置文件
    71. Logger logger = Logger.getLogger(Config.class ); //获取log4j的实例
    72. String startTmie = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
    73. logger.debug("\n**********【准备处理,正在加载文件】**********");//7
    74. logger.debug("\n\n**********每行数据间请不要有空行,以免程序误判**********");//7
    75. logger.debug("\n\n**********由于处理Excel的插件本身性能局限,请控制文件大小,以免影响加载效率。**********");//7
    76. logger.debug("\n\n**********大小在\t 7 MB \t以内,大约\t 21 万 \t行数据。**********");//7
    77. logger.debug("\n\n**********本程序每分钟约处理 7000条数据,但根据文件大小会有影响。**********");//7
    78. request.setCharacterEncoding("UTF-8");  //转码
    79. String xls_read_Address=(String)request.getParameter("xls_read_Address");//读取
    80. String xls_write_Address=(String)request.getParameter("xls_write_Address");//写入
    81. String  count_rows=(String)request.getParameter("count_rows");//自动编号
    82. String  tips_cmd=(String)request.getParameter("tips_cmd");//CMD窗口的提示方式
    83. try {
    84. DataConvert dc = new DataConvert();//数据转换工具
    85. DecimalFormat df = (DecimalFormat) NumberFormat.getPercentInstance();
    86. ArrayList<ArrayList> ls = new  ArrayList<ArrayList>();
    87. File excel_file = new File(xls_read_Address);//读取的文件路径
    88. FileInputStream input = new FileInputStream(excel_file);  //读取的文件路径
    89. XSSFWorkbook wb = new XSSFWorkbook(new BufferedInputStream(input));
    90. int sheet_numbers = wb.getNumberOfSheets();//获取表的总数
    91. logger.debug("\n\n**********共有工作表总数**********:"+sheet_numbers);//7
    92. String[] sheetnames=new String[sheet_numbers];
    93. Connection con=null;
    94. Statement  stmt=null;
    95. ResultSet  rs=null;
    96. String s_3g=null;
    97. Class.forName("oracle.jdbc.driver.OracleDriver");
    98. con = DriverManager.getConnection("jdbc:oracle:thin:@12.12.12.123:1521:gz10000","gz12345","12345");
    99. stmt = con.createStatement();
    100. for(int i=0;i<sheet_numbers;i++){//遍历所有表
    101. ArrayList<String[]> ls_a = new  ArrayList<String[]>(); //用来存储某个表 读取出来的数据
    102. Sheet sheet = wb.getSheetAt(i);  //获取 某个表
    103. sheetnames[i] = sheet.getSheetName();//获取表名,存入数组
    104. logger.debug("\n\n---正在读取和匹配工作表\t《"+sheetnames[i]+"》\t的数据---\n");//7
    105. int rows_num = sheet.getLastRowNum();//获取行数
    106. logger.debug("\n\n---表\t《"+sheetnames[i]+"》\t 共有数据---:\t"+rows_num+"\t行");//7
    107. for( int rows=0;rows<rows_num;rows++){
    108. Row row = sheet.getRow(rows);//取得某一行   对象
    109. if(row!=null&&!(row.equals(""))){
    110. int columns_num = row.getLastCellNum();//获取列数
    111. String[] s =new String[5];//初始化数组长度
    112. for( int columns=0;columns<columns_num;columns++){
    113. Cell  cell = row.getCell(columns);
    114. if(cell!=null){
    115. switch ( cell.getCellType()) {
    116. case XSSFCell.CELL_TYPE_STRING: // 字符串
    117. s[columns] = cell.getStringCellValue();
    118. if(s[columns]==null){
    119. s[columns]=" ";
    120. }
    121. break;
    122. case XSSFCell.CELL_TYPE_NUMERIC: // 数字
    123. double strCell = cell.getNumericCellValue();
    124. if(String.valueOf(strCell)==null){
    125. s[columns]=" ";
    126. }
    127. df.applyPattern("0");
    128. s[columns] = df.format(strCell);
    129. if(Double.parseDouble(s[columns])!=strCell){
    130. df.applyPattern(Double.toString(strCell));
    131. s[columns] = df.format(strCell);
    132. }
    133. break;
    134. case XSSFCell.CELL_TYPE_BLANK: // 空值
    135. s[columns]=" ";
    136. break;
    137. default:
    138. logger.debug("\n---单元格格式不支持---");
    139. break;
    140. }
    141. }
    142. }
    143. if(count_rows.equals("是")&&rows>0){
    144. s[0]=dc.intToString(rows);//自动编号
    145. }
    146. /* ******** 访问数据库 ,并判断是否3G ******** */
    147. String sql="select busiattr1 from ap_t_si_cus_spec_info where cus_phone='"+s[1]+"' and rownum=1";
    148. rs = stmt.executeQuery(sql);
    149. if(rs.next()){
    150. if(rs.getString("busiattr1")!=null){
    151. s_3g = rs.getString("busiattr1").toString().toUpperCase();
    152. }
    153. else{
    154. s_3g=" ";
    155. }
    156. }
    157. else{
    158. s_3g=" ";
    159. }
    160. /* ******** 访问结束  ******** */
    161. if(s_3g.contains("3G")){
    162. s[4]="是";//写入 “是否3G”这一列 的值,比如 “是”
    163. }
    164. if(s[4]==null){
    165. s[4]="\t";
    166. }
    167. /* CMD窗口提示方式 */
    168. if(!(tips_cmd.equals("none"))&&tips_cmd!=null&&!(tips_cmd.equals(""))) {
    169. if(tips_cmd.equals("all")){
    170. logger.debug("\n匹配中:"+s[0]+"\t"+s[1]+"\t"+s[2]+"\t"+s[3]+"\t"+ s[4]);
    171. }else
    172. if(rows%DataConvert.stringToInt(tips_cmd)==0){
    173. logger.debug("\n匹配中:"+s[0]+"\t"+s[1]+"\t"+s[2]+"\t"+s[3]+"\t"+ s[4]);
    174. }
    175. }
    176. ls_a.add(s);//添加每行数据到 ls_a
    177. }
    178. }
    179. ls.add(ls_a);       //添加 每个表 到 ls
    180. input.close();
    181. write_Excel( xls_write_Address, ls, sheetnames ,tips_cmd)  ;
    182. }
    183. } catch (IOException ex) {
    184. ex.printStackTrace();
    185. }
    186. String endTmie = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
    187. logger.debug("\n\n***************【处理完成,程序结束】***************");//7
    188. logger.debug("\n开始时间:"+startTmie);
    189. logger.debug("\n结束时间:"+endTmie);
    190. logger.debug("\n新文件输出路径为:"+xls_write_Address);
    191. }
    192. @SuppressWarnings({ "rawtypes", "unchecked" })
    193. public void write_Excel( String xls_write_Address,ArrayList<ArrayList> ls,String[] sheetnames,String tips_cmd ) throws IOException  {
    194. PropertyConfigurator.configure(class_path+"log4j.properties");//获取 log4j 配置文件
    195. Logger logger = Logger.getLogger(Config.class ); //获取log4j的实例
    196. FileOutputStream output = new FileOutputStream(new File(xls_write_Address));  //读取的文件路径
    197. SXSSFWorkbook wb = new SXSSFWorkbook(10000);//内存中保留 10000 条数据,以免内存溢出,其余写入 硬盘
    198. for(int sn=0;sn<ls.size();sn++){
    199. Sheet sheet = wb.createSheet(String.valueOf(sn));
    200. wb.setSheetName(sn, sheetnames[sn]);
    201. ArrayList<String[]> ls2 = ls.get(sn);
    202. for(int i=0;i<ls2.size();i++){
    203. Row row = sheet.createRow(i);
    204. String[] s = ls2.get(i);
    205. for(int cols=0;cols<s.length;cols++){
    206. Cell cell = row.createCell(cols);
    207. cell.setCellType(XSSFCell.CELL_TYPE_STRING);//文本格式
    208. sheet.setColumnWidth(cols, s[cols].length()*384); //设置单元格宽度
    209. cell.setCellValue(s[cols]);//写入内容
    210. }
    211. /* CMD窗口提示方式 */
    212. if(!(tips_cmd.equals("none"))&&tips_cmd!=null&&!(tips_cmd.equals(""))) {
    213. if(tips_cmd.equals("all")){
    214. logger.debug("\n写入中:"+s[0]+"\t"+s[1]+"\t"+s[2]+"\t"+s[3]+"\t"+ s[4]);
    215. }else
    216. if(i%DataConvert.stringToInt(tips_cmd)==0){
    217. logger.debug("\n写入中:"+s[0]+"\t"+s[1]+"\t"+s[2]+"\t"+s[3]+"\t"+ s[4]);
    218. }
    219. }
    220. }
    221. }
    222. wb.write(output);
    223. output.close();
    224. }
    225. }

POI操作Excel2007实例二之“SXSSFWorkbook”处理海量数据的更多相关文章

  1. poi操作excel2007(读取、生成、编辑)

    因为现在再写excel2003版的比较low,所以我在这就不介绍了,直接介绍2007,我所用的编程软件是IDEA poi操作office总共有6个jar包,在pom.xml文件中配置如下,也可下载后直 ...

  2. POI操作Excel(二)

    注意:HSSFWorkBook对应2003版Excel      XSSFWorkBook对应2007以上的Excel 一.创建时间单元格 public void helloPoi3() throws ...

  3. java使用Apache POI操作excel文件

    官方介绍 HSSF is the POI Project's pure Java implementation of the Excel '97(-2007) file format. XSSF is ...

  4. poi 操作Excel 以及大数据量导出

    maven 依赖 (版本必须一致,否则使用SXSSFworkbook 时程序会报错) <dependency> <groupId>org.apache.poi</grou ...

  5. POI 的API大全二

    1.POI结构与常用类 (1)POI介绍 Apache POI是Apache软件基金会的开源项目,POI提供API给Java程序对Microsoft Office格式档案读和写的功能. .NET的开发 ...

  6. memcached—Java操作Memcached实例

    前面博客介绍了如何在Windows操作系统中安装Memcached,总结一下如何使用Java操作Memcached实例: 代码一: package com.ghj.packageoftool; imp ...

  7. Java POI操作Excel注意点

    excel的行索引和列索引都是从0开始,而行号和列号都是从1开始 POI·操作excel基本上都是使用索引 XSSFRow对象的 row.getLastCellNum() 方法返回的是当前行最后有效列 ...

  8. Hibernate实例二

    Hibernate实例二 一.测试openSession方法和getCurrentSession方法 hebernate中可以通过上述两种方法获取session对象以对数据库进行操作,下面的代码以及注 ...

  9. Oracle 11g 物理Dataguard日常操作维护(二)

    Oracle 11g 物理Dataguard日常操作维护(二) 2017年8月25日 14:34 3.3 3.3.1 查看备库进程状态 SYS(125_7)@fpyj123> select pr ...

随机推荐

  1. Linux内核启动分析

    张超<Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 我的代码可见https://www.shiyanlo ...

  2. Linux 字符集

    摘抄自网络--/etc/sysconfig/i18n 文件:LANG="zh_CN.GB18030"SUPPORTED="zh_CN.GB18030:zh_CN:zh:e ...

  3. poj 1988 Cube Stacking && codevs 1540 银河英雄传说(加权并茶几)

    #include<iostream> #include<cstdio> #include<cstring> #define maxn 30010 using nam ...

  4. 使用linux操作系统的公司服务器有哪些品牌

    服务器硬件是什么牌子的? 操心系统有哪些?cpu是哪些?

  5. android 检查网络是否可用,如果不可用弹出设置,让用户改变

    /** * 校验网络,如果没有网络,返回true * * @return boolean */ @Override public boolean hasInternetConnected() { Co ...

  6. .NET 编译器(”Roslyn“)介绍

    介绍 一般来说,编译器是一个黑箱,源代码从一端进入,然后箱子中发生一些奇妙的变化,最后从另一端出来目标文件或程序集.编译器施展它们的魔法,它们必须对所处理的代码进行深入的理解,不过相关知识不是每个人都 ...

  7. iOS 网络与多线程--2.同步Get方式的网络请求(阻塞)

    通过Get请求方式同步获取网络数据.一旦发送同步请求,程序将停止用户交互,直至服务器返回数据. 之后在视图控制器文件(ViewController.m)内添加以下代码 在viewDidLoad函数内添 ...

  8. 监听UITabBarItem来拦截是否要跳转

    情景是这样的: 我需要在用户点击"我的"的时候, 判断是否已经登录, 如果没有, 就不进入该界面, 而是跳转到用户登录界面, 所以这里我需要进行UITabBarItem点击事件的拦 ...

  9. log4j日志输出使用教程

    Log4j是帮助开发人员进行日志输出管理的API类库.它最重要的特点就可以配置文件灵活的设置日志信息的优先级.日志信息的输出目的地以及日志信息的输出格式.Log4j除了可以记录程序运行日志信息外还有一 ...

  10. nginx虚拟配置

    server { listen 8080; server_name www.manihome.com ; root "D:/WWW/mnmnh_2015"; location / ...