乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      Java解析excel工具easyexcel 助你快速簡單避免OOM

       wwq圖書世界 2019-10-25

      原文鏈接:https://www./archives/javatool001

      Java解析、生成Excel比較有名的框架有Apache poi、jxl。但他們都存在一個嚴(yán)重的問題就是非常的耗內(nèi)存,poi有一套SAX模式的API可以一定程度的解決一些內(nèi)存溢出的問題,但POI還是有一些缺陷,比如07版Excel解壓縮以及解壓后存儲都是在內(nèi)存中完成的,內(nèi)存消耗依然很大。easyexcel重寫了poi對07版Excel的解析,能夠原本一個3M的excel用POI sax依然需要100M左右內(nèi)存降低到KB級別,并且再大的excel不會出現(xiàn)內(nèi)存溢出,03版依賴POI的sax模式。在上層做了模型轉(zhuǎn)換的封裝,讓使用者更加簡單方便

      easyexcel核心功能

      • 讀任意大小的03、07版Excel不會OOM
      • 讀Excel自動通過注解,把結(jié)果映射為java模型
      • 讀Excel支持多sheet
      • 讀Excel時候是否對Excel內(nèi)容做trim()增加容錯
      • 寫小量數(shù)據(jù)的03版Excel(不要超過2000行)
      • 寫任意大07版Excel不會OOM
      • 寫Excel通過注解將表頭自動寫入Excel
      • 寫Excel可以自定義Excel樣式 如:字體,加粗,表頭顏色,數(shù)據(jù)內(nèi)容顏色
      • 寫Excel到多個不同sheet
      • 寫Excel時一個sheet可以寫多個Table
      • 寫Excel時候自定義是否需要寫表頭

      快速使用

      1. JAR包依賴

      使用前最好咨詢下最新版,或者到mvn倉庫搜索一下easyexcel的最新版

      <dependency>
          <groupId>com.alibaba</groupId>
          <artifactId>easyexcel</artifactId>
          <version>{latestVersion}</version>
      </dependency>

      2. 讀取Excel

      使用easyexcel解析03、07版本的Excel只是ExcelTypeEnum不同,其他使用完全相同,使用者無需知道底層解析的差異。

      無java模型直接把excel解析的每行結(jié)果以List返回 在ExcelListener獲取解析結(jié)果
      讀excel代碼示例如下:

      
          @Test
          public void testExcel2003NoModel() {
              InputStream inputStream = getInputStream("loan1.xls");
              try {
                  // 解析每行結(jié)果在listener中處理
                  ExcelListener listener = new ExcelListener();
      
                  ExcelReader excelReader = new ExcelReader(inputStream, ExcelTypeEnum.XLS, null, listener);
                  excelReader.read();
              } catch (Exception e) {
      
              } finally {
                  try {
                      inputStream.close();
                  } catch (IOException e) {
                      e.printStackTrace();
                  }
              }
          }

      ExcelListener示例代碼如下:

      
       /* 解析監(jiān)聽器,
       * 每解析一行會回調(diào)invoke()方法。
       * 整個excel解析結(jié)束會執(zhí)行doAfterAllAnalysed()方法
       *
       * 下面只是我寫的一個樣例而已,可以根據(jù)自己的邏輯修改該類。
       * @author jipengfei
       * @date 2017/03/14
       */
      public class ExcelListener extends AnalysisEventListener {
      
          //自定義用于暫時存儲data。
          //可以通過實例獲取該值
          private List<Object> datas = new ArrayList<Object>();
          public void invoke(Object object, AnalysisContext context) {
              System.out.println("當(dāng)前行:"+context.getCurrentRowNum());
              System.out.println(object);
              datas.add(object);//數(shù)據(jù)存儲到list,供批量處理,或后續(xù)自己業(yè)務(wù)邏輯處理。
              doSomething(object);//根據(jù)自己業(yè)務(wù)做處理
          }
          private void doSomething(Object object) {
              //1、入庫調(diào)用接口
          }
          public void doAfterAllAnalysed(AnalysisContext context) {
             // datas.clear();//解析結(jié)束銷毀不用的資源
          }
          public List<Object> getDatas() {
              return datas;
          }
          public void setDatas(List<Object> datas) {
              this.datas = datas;
          }
      }

      有java模型映射
      java模型寫法如下:

      public class LoanInfo extends BaseRowModel {
          @ExcelProperty(index = 0)
          private String bankLoanId;
      
          @ExcelProperty(index = 1)
          private Long customerId;
      
          @ExcelProperty(index = 2,format = "yyyy/MM/dd")
          private Date loanDate;
      
          @ExcelProperty(index = 3)
          private BigDecimal quota;
      
          @ExcelProperty(index = 4)
          private String bankInterestRate;
      
          @ExcelProperty(index = 5)
          private Integer loanTerm;
      
          @ExcelProperty(index = 6,format = "yyyy/MM/dd")
          private Date loanEndDate;
      
          @ExcelProperty(index = 7)
          private BigDecimal interestPerMonth;
      
          @ExcelProperty(value = {"一級表頭","二級表頭"})
          private BigDecimal sax;
      }

      @ExcelProperty(index = 3)數(shù)字代表該字段與excel對應(yīng)列號做映射,也可以采用 @ExcelProperty(value = {“一級表頭”,”二級表頭”})用于解決不確切知道excel第幾列和該字段映射,位置不固定,但表頭的內(nèi)容知道的情況。

          @Test
          public void testExcel2003WithReflectModel() {
              InputStream inputStream = getInputStream("loan1.xls");
              try {
                  // 解析每行結(jié)果在listener中處理
                  AnalysisEventListener listener = new ExcelListener();
      
                  ExcelReader excelReader = new ExcelReader(inputStream, ExcelTypeEnum.XLS, null, listener);
      
                  excelReader.read(new Sheet(1, 2, LoanInfo.class));
              } catch (Exception e) {
      
              } finally {
                  try {
                      inputStream.close();
                  } catch (IOException e) {
                      e.printStackTrace();
                  }
              }
      
          }

      帶模型解析與不帶模型解析主要在構(gòu)造new Sheet(1, 2, LoanInfo.class)時候包含class。Class需要繼承BaseRowModel暫時BaseRowModel沒有任何內(nèi)容,后面升級可能會增加一些默認(rèn)的數(shù)據(jù)。

      3. 生成Excel

      每行數(shù)據(jù)是List無表頭

              OutputStream out = new FileOutputStream("/Users/jipengfei/77.xlsx");
              try {
                  ExcelWriter writer = new ExcelWriter(out, ExcelTypeEnum.XLSX,false);
                  //寫第一個sheet, sheet1  數(shù)據(jù)全是List<String> 無模型映射關(guān)系
                  Sheet sheet1 = new Sheet(1, 0);
                  sheet1.setSheetName("第一個sheet");
                  writer.write(getListString(), sheet1);
                  writer.finish();
              } catch (Exception e) {
                  e.printStackTrace();
              } finally {
                  try {
                      out.close();
                  } catch (IOException e) {
                      e.printStackTrace();
                  }
              }

      每行數(shù)據(jù)是一個java模型有表頭—-表頭層級為一

      生成Excel格式如下圖:

      模型寫法如下:

      public class ExcelPropertyIndexModel extends BaseRowModel {
      
          @ExcelProperty(value = "姓名" ,index = 0)
          private String name;
      
          @ExcelProperty(value = "年齡",index = 1)
          private String age;
      
          @ExcelProperty(value = "郵箱",index = 2)
          private String email;
      
          @ExcelProperty(value = "地址",index = 3)
          private String address;
      
          @ExcelProperty(value = "性別",index = 4)
          private String sax;
      
          @ExcelProperty(value = "高度",index = 5)
          private String heigh;
      
          @ExcelProperty(value = "備注",index = 6)
          private String last;
      }

      @ExcelProperty(value = “姓名”,index = 0) value是表頭數(shù)據(jù),默認(rèn)會寫在excel的表頭位置,index代表第幾列。

          @Test
          public void test1() throws FileNotFoundException {
              OutputStream out = new FileOutputStream("/Users/jipengfei/78.xlsx");
              try {
                  ExcelWriter writer = new ExcelWriter(out, ExcelTypeEnum.XLSX);
                  //寫第一個sheet, sheet1  數(shù)據(jù)全是List<String> 無模型映射關(guān)系
                  Sheet sheet1 = new Sheet(1, 0,ExcelPropertyIndexModel.class);
                  writer.write(getData(), sheet1);
                  writer.finish();
              } catch (Exception e) {
                  e.printStackTrace();
              } finally {
                  try {
                      out.close();
                  } catch (IOException e) {
                      e.printStackTrace();
                  }
              }
          }

      每行數(shù)據(jù)是一個java模型有表頭—-表頭層級為多層級

      生成Excel格式如下圖:

      java模型寫法如下:

      public class MultiLineHeadExcelModel extends BaseRowModel {
      
          @ExcelProperty(value = {"表頭1","表頭1","表頭31"},index = 0)
          private String p1;
      
          @ExcelProperty(value = {"表頭1","表頭1","表頭32"},index = 1)
          private String p2;
      
          @ExcelProperty(value = {"表頭3","表頭3","表頭3"},index = 2)
          private int p3;
      
          @ExcelProperty(value = {"表頭4","表頭4","表頭4"},index = 3)
          private long p4;
      
          @ExcelProperty(value = {"表頭5","表頭51","表頭52"},index = 4)
          private String p5;
      
          @ExcelProperty(value = {"表頭6","表頭61","表頭611"},index = 5)
          private String p6;
      
          @ExcelProperty(value = {"表頭6","表頭61","表頭612"},index = 6)
          private String p7;
      
          @ExcelProperty(value = {"表頭6","表頭62","表頭621"},index = 7)
          private String p8;
      
          @ExcelProperty(value = {"表頭6","表頭62","表頭622"},index = 8)
          private String p9;
      }

      寫Excel寫法同上,只需將ExcelPropertyIndexModel.class改為MultiLineHeadExcelModel.class

      一個Excel多個sheet寫法

          @Test
          public void test1() throws FileNotFoundException {
      
              OutputStream out = new FileOutputStream("/Users/jipengfei/77.xlsx");
              try {
                  ExcelWriter writer = new ExcelWriter(out, ExcelTypeEnum.XLSX,false);
                  //寫第一個sheet, sheet1  數(shù)據(jù)全是List<String> 無模型映射關(guān)系
                  Sheet sheet1 = new Sheet(1, 0);
                  sheet1.setSheetName("第一個sheet");
                  writer.write(getListString(), sheet1);
      
                  //寫第二個sheet sheet2  模型上打有表頭的注解,合并單元格
                  Sheet sheet2 = new Sheet(2, 3, MultiLineHeadExcelModel.class, "第二個sheet", null);
                  sheet2.setTableStyle(getTableStyle1());
                  writer.write(getModeldatas(), sheet2);
      
                  //寫sheet3  模型上沒有注解,表頭數(shù)據(jù)動態(tài)傳入
                  List<List<String>> head = new ArrayList<List<String>>();
                  List<String> headCoulumn1 = new ArrayList<String>();
                  List<String> headCoulumn2 = new ArrayList<String>();
                  List<String> headCoulumn3 = new ArrayList<String>();
                  headCoulumn1.add("第一列");
                  headCoulumn2.add("第二列");
                  headCoulumn3.add("第三列");
                  head.add(headCoulumn1);
                  head.add(headCoulumn2);
                  head.add(headCoulumn3);
                  Sheet sheet3 = new Sheet(3, 1, NoAnnModel.class, "第三個sheet", head);
                  writer.write(getNoAnnModels(), sheet3);
                  writer.finish();
              } catch (Exception e) {
                  e.printStackTrace();
              } finally {
                  try {
                      out.close();
                  } catch (IOException e) {
                      e.printStackTrace();
                  }
              }
          }

      一個sheet中有多個表格

          @Test
          public void test2() throws FileNotFoundException {
              OutputStream out = new FileOutputStream("/Users/jipengfei/77.xlsx");
              try {
                  ExcelWriter writer = new ExcelWriter(out, ExcelTypeEnum.XLSX,false);
      
                  //寫sheet1  數(shù)據(jù)全是List<String> 無模型映射關(guān)系
                  Sheet sheet1 = new Sheet(1, 0);
                  sheet1.setSheetName("第一個sheet");
                  Table table1 = new Table(1);
                  writer.write(getListString(), sheet1, table1);
                  writer.write(getListString(), sheet1, table1);
      
                  //寫sheet2  模型上打有表頭的注解
                  Table table2 = new Table(2);
                  table2.setTableStyle(getTableStyle1());
                  table2.setClazz(MultiLineHeadExcelModel.class);
                  writer.write(getModeldatas(), sheet1, table2);
      
                  //寫sheet3  模型上沒有注解,表頭數(shù)據(jù)動態(tài)傳入,此情況下模型field順序與excel現(xiàn)實順序一致
                  List<List<String>> head = new ArrayList<List<String>>();
                  List<String> headCoulumn1 = new ArrayList<String>();
                  List<String> headCoulumn2 = new ArrayList<String>();
                  List<String> headCoulumn3 = new ArrayList<String>();
                  headCoulumn1.add("第一列");
                  headCoulumn2.add("第二列");
                  headCoulumn3.add("第三列");
                  head.add(headCoulumn1);
                  head.add(headCoulumn2);
                  head.add(headCoulumn3);
                  Table table3 = new Table(3);
                  table3.setHead(head);
                  table3.setClazz(NoAnnModel.class);
                  table3.setTableStyle(getTableStyle2());
                  writer.write(getNoAnnModels(), sheet1, table3);
                  writer.write(getNoAnnModels(), sheet1, table3);
      
                  writer.finish();
              } catch (Exception e) {
                  e.printStackTrace();
              } finally {
                  try {
                      out.close();
                  } catch (IOException e) {
                      e.printStackTrace();
                  }
              }
          }

      4. 測試數(shù)據(jù)分析

      從上面的性能測試可以看出easyexcel在解析耗時上比poiuserModel模式弱了一些。主要原因是我內(nèi)部采用了反射做模型字段映射,中間我也加了cache,但感覺這點差距可以接受的。但在內(nèi)存消耗上差別就比較明顯了,easyexcel在后面文件再增大,內(nèi)存消耗幾乎不會增加了。但poi userModel就不一樣了,簡直就要爆掉了。想想一個excel解析200M,同時有20個人再用估計一臺機(jī)器就掛了。

      5. 百萬數(shù)據(jù)解析對比

      easyexcel解析百萬數(shù)據(jù)內(nèi)存圖如下:
      easyexcel解析百萬數(shù)據(jù)內(nèi)存圖

      poi解析百萬數(shù)據(jù)內(nèi)存圖如下:
      poi解析百萬數(shù)據(jù)內(nèi)存圖

      從上面兩圖可以看出,easyexcel解析時內(nèi)存消耗很少,最多消耗不到50M;POI解析過程中直接飄升到1.5G左右,系統(tǒng)內(nèi)存耗盡,程序掛掉。

      GitHub地址:https://github.com/alibaba/easyexcel

        本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
        轉(zhuǎn)藏 分享 獻(xiàn)花(0

        0條評論

        發(fā)表

        請遵守用戶 評論公約

        類似文章 更多