張慧的博客

          張慧的博客

            BlogJava :: 首頁 :: 聯系 :: 聚合  :: 管理
            45 Posts :: 0 Stories :: 24 Comments :: 0 Trackbacks

          在Java Web開發中,經常需要導出大量的數據到Excel,使用POI、JXL直接生成Excel,很容易就造成內存溢出了。

            1、有一種方式,就是把數據寫成csv格式文件。

            1)csv文件可以直接用Excel打開。

            2)寫csv文件的效率和寫txt文件的效率一樣高。

            3)同樣的數據內容,生成的csv文件的大小遠遠小于生成的Excel文件。

            從以上優點就可以看出生成csv文件消耗的內存絕對小于生成Excel文件。

            2、按一定的格式去生成csv文件,在Excel中打開的時候就是完整的行和列格式。

            例如:在Excel中的格式:

                                             

            那么,在csv文件中格式就必須為:

                                            

            就是說,列和列之間,需要用英文輸入法狀態下的逗號","間隔:風云第一刀,古龍。

            3、在Struts2中導出數據到Excel,一個簡單的例子。

            CsvAction,生成csv文件,并且將生成的csv文件完整路徑傳遞到下載Action。

          package cn.luxh.struts2.action;

          import java.io.FileWriter;
          import java.io.IOException;
          import java.text.SimpleDateFormat;
          import java.util.ArrayList;
          import java.util.Date;
          import java.util.List;

          import cn.luxh.struts2.entity.Novel;

          import com.opensymphony.xwork2.ActionSupport;


          /**
           * 導出數據到csv文件
           * 
          @author Luxh
           
          */
          public class CsvAction extends ActionSupport {

              private static final long serialVersionUID = -2862629695443964658L;
              
              /**
               * 包含完整路徑的文件名
               * 傳遞給下載Action進行下載
               
          */
              private String fileName;
              
              
              /**
               * 導出數據
               
          */
              public String exportData2CSV() {
                  List<Novel> novels = getNovels();
                  fileName = "D:/novels.csv";
                  writeData2CSV(novels,fileName);
                  return SUCCESS;
                  
              }
              
              /**
               * 構造一些數據
               * 實際上可能是從數據庫中把大量的數據查出來
               
          */
              private List<Novel> getNovels() {
                  List<Novel> novels = new ArrayList<Novel>();
                  
                  Novel novel1 = new Novel("風云第一刀","古龍",new Date());
                  Novel novel2 = new Novel("書劍恩仇錄","金庸",new Date());
                  Novel novel3 = new Novel("陸小鳳傳奇","古龍",new Date());
                  Novel novel4 = new Novel("鹿鼎記","金庸",new Date());
                  
                  novels.add(novel1);
                  novels.add(novel2);
                  novels.add(novel3);
                  novels.add(novel4);
                  
                  return novels;
              }
              
              /**
               * 把數據按一定的格式寫到csv文件中
               * 
          @param novels     數據集合
               * 
          @param fileName  csv文件完整路徑
               
          */
              public void writeData2CSV(List<Novel> novels,String fileName) {
                  FileWriter fw = null;
                  try {
                      fw = new FileWriter(fileName);
                      //輸出標題頭
                      
          //注意列之間用","間隔,寫完一行需要回車換行"\r\n"
                      String title = "序號,小說名稱,作者,出版日期\r\n";
                      fw.write(title);
                      
                      String content = null;
                      SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
                      for(int i=0;i<novels.size();i++) {
                          Novel novel = novels.get(i);
                          //注意列之間用","間隔,寫完一行需要回車換行"\r\n"
                          content =(i+1)+","+novel.getName()+","+novel.getAuthor()+","+sdf.format(novel.getPublishDate())+"\r\n";
                          fw.write(content);
                      }
                  }catch(Exception e) {
                      e.printStackTrace();
                      throw new RuntimeException(e);
                  }finally {
                      try {
                          if(fw!=null) {
                              fw.close();
                          }
                      } catch (IOException e) {
                          e.printStackTrace();
                      }
                  }
              }

          }

          復制代碼

            配置文件:

          <!--將csv文件路徑傳遞到公共的下載Action進行下載  -->
                   <action name="exportData2CSV" class="cn.luxh.struts2.action.CsvAction" method="exportData2CSV">
                      <result type="redirectAction">
                          <param name="actionName">download</param>
                          <param name="nameSpace">/download</param>
                          <!--附件的完整路徑 ,傳遞給下載Action -->
                          <param name="fileName">${fileName}</param>
                      </result>
                  </action>

            提供下載功能的Action參考http://www.cnblogs.com/luxh/archive/2012/07/01/2571778.html

            4、看一下同樣的數據內容,csv文件和Excel文件的大小對比: 

                                                  

           

           

           

           

           

           

           

            

          posted on 2012-07-10 00:43 張慧 閱讀(7381) 評論(1)  編輯  收藏

          Feedback

          # re: 導出大量數據到Excel的一種方式 2012-07-10 09:00 Niko7
          導出excel確實有些麻煩,不能流式處理,導致占用比較大的內存,很容易導致內存溢出;并且excel的數據量是有限制的,不能超過65536行。
          一旦超過,將無法生成excel文件。

          用csv方式導出,則可以像導出txt一樣,以文本流的方式進行流式處理,不但能導出海量信息,而且流式處理占用內存極低,服務器對瀏覽器的響應也是非常迅速的。輕松導出幾百萬行數據,理論上是不限量的。

          不過,csv方式導出也存在問題:
          首先,如果用excel來打開csv,超過65536行的數據都會看不見,這是excel程序的問題。

          其次,如果你要導出一個身份證號碼,手機號碼,郵政編碼等,純數字構成的字符串,在excel中打開csv時,這些字段很容易被識別成數字,造成誤解。
          解決方法是在字符串前加“'”(單引號),然而這樣處理后,excel打開scv時會看到這個“'”,又不對了,并且單擊該單元格再離開后,這個單引號會自動消失,這是'在excel中的特殊用途導致的,如果此時再保存文件,文件中的'會丟失,如果再打開該csv文件,問題就更嚴重了,編碼全成數字了(因為'丟了)!
          看來這也是excel的問題。

          上面兩個問題按下不說的話,那么csv文件還是有些基本規則的,比如用""括起來那么里面的","不會作為分隔符等轉義操作。

          總體而言,我也傾向于csv格式,它可以流式處理。  回復  更多評論
            


          只有注冊用戶登錄后才能發表評論。


          網站導航:
           
          主站蜘蛛池模板: 南阳市| 呼和浩特市| 扶风县| 柳河县| 宿迁市| 锡林浩特市| 花莲市| 浪卡子县| 咸丰县| 独山县| 克东县| 贵港市| 高雄市| 赣榆县| 天长市| 永春县| 商河县| 师宗县| 长阳| 陵水| 大关县| 云和县| 乌海市| 科技| 汶上县| 天门市| 宝坻区| 堆龙德庆县| 龙山县| 吴忠市| 宾川县| 宁海县| 共和县| 上蔡县| 西藏| 苗栗市| 吉林市| 文山县| 隆昌县| 柞水县| 永靖县|