分類專欄:
用過poi的人都知道,在poi以前的版本中並不支援大資料量的處理,如果資料量過多還會常報oom錯誤,
這時候調整jvm的配置引數也不是乙個好對策(注:jdk在32位系統中支援的記憶體不能超過2個g,而在64位中沒有限制,但是在64位的系統中,效能並不是太好),好在poi3.8版本新出來了乙個sxssfworkbook物件,它就是用來解決大資料量以及超大資料量的匯入匯出操作的,但是sxssfworkbook只支援.xlsx格式,不支援.xls格式的excel檔案。
這裡普及一下,在poi中使用hssf物件時,excel 2003最多隻允許儲存65536條資料,一般用來處理較少的資料量,這時對於百萬級別資料,excel肯定容納不了,而且在計算機效能稍低的機器上測試,就很容易導致堆溢位。而當我公升級到xssf物件時,它可以直接支援excel2007以上版本,因為它採用ooxml格式。這時excel可以支援1048576條資料,單個sheet表就支援近104萬條資料了,雖然這時匯出100萬資料能滿足要求,但使用xssf測試後發現偶爾還是會發生堆溢位,所以也不適合百萬資料的匯出。
現在我們知道excel2007及以上版本可以輕鬆實現儲存百萬級別的資料,但是系統中的大量資料是如何能夠快速準確的匯入到excel中這好像是個難題,對於一般的web系統,我們為了解決成本,基本都是使用的入門級web伺服器tomcat,既然我們不推薦調整jvm的大小,那我們就要針對我們的**來解決我們要解決的問題。在poi3.8之後新增加了乙個類,sxssfworkbook,採用當資料加工時不是類似前面版本的物件,它可以控制excel資料占用的記憶體,他通過控制在記憶體中的行數來實現資源管理,即當建立物件超過了設定的行數,它會自動重新整理記憶體,將資料寫入檔案,這樣導致列印時,占用的cpu,和記憶體很少。但有人會說了,我用過這個類啊,他好像並不能完全解決,當資料量超過一定量後還是會記憶體溢位的,而且時間還很長。對你只是用了這個類,但是你並沒有針對你的需求進行相應的設計,僅僅是用了,所以接下來我要說的問題就是,如何通過sxssfworkbook以及相應的寫入設計來實現百萬級別的資料快速寫入。
我先舉個例子,以前我們資料庫中存在大量的資料,我們要查詢,怎麼辦?我們在沒有經過設計的時候是這樣來處理的,先寫乙個集合,然後執行jdbc,將返回的結果賦值給list,然後再返回到頁面上,但是當資料量大的時候,就會出現資料無法返回,記憶體溢位的情況,於是我們在有限的時間和空間下,通過分頁將資料一頁一頁的顯示出來,這樣可以避免了大資料量資料對記憶體的占用,也提高了使用者的體驗,在我們要匯出的百萬資料也是乙個道理,記憶體突發性占用,我們可以限制匯出資料所占用的記憶體,這裡我先建立乙個list容器,list中開闢10000行的儲存空間,每次儲存10000行,用完了將內容清空,然後重複利用,這樣就可以有效控制記憶體,所以我們的設計思路就基本形成了,所以分頁資料匯出共有以下3個步驟:
1、求資料庫中待匯出資料的行數
2、根據行數求資料提取次數
3、按次數將資料寫入檔案
通過以上步驟在效率和使用者體驗性上都有了很高的提高,接下來上**
到目前已經可以實現百萬資料的匯出了,但是當我們的業務資料超過200萬,300萬了呢?如何解決?public
void
exportbigdataexcel
(valuedatadto valuedatadto, string path)
throws ioexception
list.clear();
// 每次儲存len行,用完了將內容清空,以便記憶體可重複利用
}fileoutputstream fileout =
new fileoutputstream(path);
wb.write(fileout);
fileout.close();
wb.dispose();
}
這時,直接列印資料到乙個工作簿的乙個工作表是實現不了的,必須拆分到多個工作表,或者多個工作簿中才能實現。因為乙個sheet最多行數為1048576。
下面就以這種思路提供另外一種解決方案,直接上**(後面會附上測試資料庫,及案例需要的jar包)
資料庫截圖:public
static
void
main(string args) throws exception
public
void
jdbcex(boolean isclose) throws instantiationexception, illegalacces***ception,
classnotfoundexception, sqlexception, ioexception, interruptedexception
rowno++;
nrow = sheet.createrow(pagerowno++);
//新建行物件
// 列印每行,每行有6列資料 rsmd.getcolumncount()==6 --- 列屬性的個數
for(
int j=
0;jncell = nrow.createcell(j);
ncell.setcellvalue(rs.getstring(j+
1));
}if(rowno%
10000==
0)// thread.sleep(1); //休息一下,防止對cpu占用,其實影響不大
}long finishedtime = system.currenttimemillis();
//處理完成時間
system.
out.println(
"finished execute time: " + (finishedtime - starttime)/
1000 +
"m");
fileoutputstream fout =
new fileoutputstream(xlsfile);
wb.write(fout);
fout.flush();
//重新整理緩衝區
fout.close();
long stoptime = system.currenttimemillis();
//寫檔案時間
system.
out.println(
"write xlsx file time: " + (stoptime - starttime)/
1000 +
"m");
if(isclose)
}//執行關閉流的操作
private
void
close(resultset rs, statement stmt, connection conn ) throws sqlexception
![](https://pic.w3help.cc/06a/9a5cadb5b0dc2d04e01fdc73e8186.jpeg)
案例執行結果截圖:
完美!!!!
POI匯入匯出
利用poi可以實現excel檔案匯入和匯出功能 本例子結合了springboot做demo pom檔案 1.8 org.springframework.boot spring boot starter 1.5.4.release org.springframework.boot spring boo...
POI匯出資料
很簡單的乙個資料匯出啊,因為我的需求只有兩個字段,使用者名稱及手機號所以簡單的一批,記錄一下,方便能對大家有幫助,這個poi也非常的簡單。上 poi 的 jar依賴 org.apache.poi poi3.6 上一下excel工具類 新建 excelutil 類 package com.tianru...
POI匯出資料
workbook wb new hssfworkbook 新建乙個wb工作簿 sheet sheet wb.createsheet 學生的sheet頁 row row sheet.createrow 0 反射獲取屬性名作為表頭 這裡也可以讓別人傳 field fields clz.getdeclar...