HSSF XSSF SXSSF

1、POI操作EXCEL工作簿的三種類型(都是實(shí)現(xiàn)Workbook接口):

  • HSSFWorkbook
  • XSSFWorkbook
  • SXSSFWorkbook

2、一般使用流程

1.創(chuàng)建工作簿W(wǎng)orkbook
2.創(chuàng)建Sheet
3.創(chuàng)建行Row
4.創(chuàng)建單元格Cell

3、HSSFWorkbook

HSSFWorkbook是操作Excel2003以前(包括2003)的版本瘟裸,擴(kuò)展名為.xls庄吼,所以每個(gè)Sheet局限就是導(dǎo)出的行數(shù)至多為65535行,一般不會(huì)發(fā)生內(nèi)存不足的情況(OOM)膝但。

4、XSSFWorkbook

這種形式的出現(xiàn)是由于HSSFWorkbook的局限性而產(chǎn)生的谤草,因?yàn)槠渌鶎?dǎo)出的行數(shù)比較少跟束,并且只針對(duì)Excel2003以前(包括2003)的版本的版本莺奸,所以 XSSFWookbook應(yīng)運(yùn)而生,其對(duì)應(yīng)的是EXCEL2007以后的版本(1048576行冀宴,16384列)擴(kuò)展名.xlsx憾筏,每個(gè)Sheet最多可以導(dǎo)出104萬行,不過這樣就伴隨著一個(gè)OOM內(nèi)存溢出的問題花鹅,原因是你所創(chuàng)建的sheet row cell 等此時(shí)是存在內(nèi)存中的氧腰,隨著數(shù)據(jù)量增大 ,內(nèi)存的需求量也就增大刨肃,那么很大可能就是要OOM了古拴。

5、對(duì)于不同版本的EXCEL文檔要使用不同的工具類真友,如果使用錯(cuò)了程序會(huì)出現(xiàn)異常黄痪。

6、SXSSFWorkbook

從POI 3.8版本開始盔然,提供了一種基于XSSFWorkbook的低內(nèi)存占用的工作簿SXSSFWorkbook桅打。

SXSSF (Streaming Usermodel API)

SXSSF (package: org.apache.poi.xssf.streaming) is an API-compatible streaming extension of XSSF to be used when very large spreadsheets have to be produced, and heap space is limited. SXSSF achieves its low memory footprint by limiting access to the rows that are within a sliding window, while XSSF gives access to all rows in the document. Older rows that are no longer in the window become inaccessible, as they are written to the disk.
You can specify the window size at workbook construction time via new SXSSFWorkbook(int windowSize) or you can set it per-sheet via SXSSFSheet#setRandomAccessWindowSize(int windowSize)
When a new row is created via createRow() and the total number of unflushed records would exceed the specified window size, then the row with the lowest index value is flushed and cannot be accessed via getRow() anymore.
The default window size is 100 and defined by SXSSFWorkbook.DEFAULT_WINDOW_SIZE.
A windowSize of -1 indicates unlimited access. In this case all records that have not been flushed by a call to flushRows() are available for random access.
Note that SXSSF allocates temporary files that you must always clean up explicitly, by calling the dispose method.
SXSSFWorkbook defaults to using inline strings instead of a shared strings table. This is very efficient, since no document content needs to be kept in memory, but is also known to produce documents that are incompatible with some clients. With shared strings enabled all unique strings in the document has to be kept in memory. Depending on your document content this could use a lot more resources than with shared strings disabled.
Please note that there are still things that still may consume a large amount of memory based on which features you are using, e.g. merged regions, hyperlinks, comments, ... are still only stored in memory and thus may require a lot of memory if used extensively.
Carefully review your memory budget and compatibility needs before deciding whether to enable shared strings or not.

引用官方的介紹,簡(jiǎn)單概括就是:
SXSSF是對(duì)XSSF的一種流式擴(kuò)展愈案,特點(diǎn)是采用了滑動(dòng)窗口的機(jī)制挺尾,低內(nèi)存占用,主要用于數(shù)據(jù)量非常大的電子表格而虛擬機(jī)堆有限的情況站绪。

原理是利用了滑動(dòng)窗口機(jī)制遭铺。
SXSSFWorkbook.DEFAULT_WINDOW_SIZE默認(rèn)值是100,表示在內(nèi)存中最多存在100個(gè)Row對(duì)象恢准,當(dāng)寫第101個(gè)Row對(duì)象的時(shí)候就會(huì)把第1個(gè)Row對(duì)象以XML格式寫入C:\Users\wange\AppData\Local\Temp路徑下的臨時(shí)文件中魂挂,后面的以此類推,始終保持內(nèi)存中最多存在100個(gè)Row對(duì)象馁筐。

SXSSFWorkbook默認(rèn)使用內(nèi)聯(lián)字符串而不是共享字符串表(SharedStringsTable)涂召。啟用共享字符串時(shí),文檔中的所有唯一字符串都必須保存在內(nèi)存中敏沉,因此會(huì)占用更多的內(nèi)存果正。

/**
 * workbook - 模板工作簿
 * rowAccessWindowSize - 保存在內(nèi)存中,直到刷新的行數(shù)赦抖。
 * compressTmpFiles - 是否對(duì)臨時(shí)文件使用gzip壓縮舱卡,臨時(shí)文件可能占用過大的情況
 * useSharedStringsTable - 是否使用共享字符串表
 */
SXSSFWorkbook(XSSFWorkbook workbook, int rowAccessWindowSize, boolean compressTmpFiles, boolean useSharedStringsTable)

與XSSF的對(duì)比辅肾,在一個(gè)時(shí)間點(diǎn)上队萤,只可以訪問一定數(shù)量的Row;不再支持Sheet.clone()矫钓;不再支持公式的求值要尔。但是除了滑動(dòng)窗口舍杜,其余的EXCLE操作仍然使用的是XSSF的API。
另外官方提示導(dǎo)出EXCEL后應(yīng)該調(diào)用wb.dispose()來刪除之前保存的臨時(shí)文件赵辕。

//The example below writes a sheet with a window of 100 rows. When the row count reaches 101, the row with rownum=0 is flushed to disk and removed from memory, when rownum reaches 102 then the row with rownum=1 is flushed, etc.

package cn.nubia;

import org.junit.Assert;
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.ss.util.CellReference;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;

import java.io.FileOutputStream;
import java.io.IOException;

public class App 
{
    public static void main( String[] args ) throws IOException {
        SXSSFWorkbook wb = new SXSSFWorkbook(100); // keep 100 rows in memory, exceeding rows will be flushed to disk
        Sheet sh = wb.createSheet();
        for(int rownum = 0; rownum < 1000; rownum++){
            Row row = sh.createRow(rownum);
            for(int cellnum = 0; cellnum < 10; cellnum++){
                Cell cell = row.createCell(cellnum);
                String address = new CellReference(cell).formatAsString();
                cell.setCellValue(address);
            }

        }

        // Rows with rownum < 900 are flushed and not accessible
        for(int rownum = 0; rownum < 900; rownum++){
            Assert.assertNull(sh.getRow(rownum));
        }

        // ther last 100 rows are still in memory
        for(int rownum = 900; rownum < 1000; rownum++){
            Assert.assertNotNull(sh.getRow(rownum));
        }

        FileOutputStream out = new FileOutputStream("C:\\Users\\wange\\Desktop\\wtf.xlsx");
        wb.write(out);
        out.close();

        // dispose of temporary files backing this workbook on disk
        wb.dispose();
    }
}

wb.write(out)通過源碼了解到過程是
1既绩、將wb的所有sheet調(diào)用flushRows()移出內(nèi)存,寫入臨時(shí).xml文件中
2还惠、生成了一個(gè)臨時(shí).xlsx文件將wb的一些模板數(shù)據(jù)寫入這個(gè)臨時(shí)文件
3饲握、將這個(gè)臨時(shí).xlsx文件轉(zhuǎn)成ZipFile,遍歷所有ZipEntry來獲取Sheet蚕键,如果沒有Sheet則直接復(fù)制流救欧。
4、如果能夠獲取到Sheet的則是那些臨時(shí).xml文件锣光,在對(duì)這些文件進(jìn)行解析并追蹤寫入導(dǎo)出文件中笆怠。
(這邊可能是涉及到了一些EXCEL文件格式的原理,就不深入研究了)

SXSSFWorkbook wb = new SXSSFWorkbook(-1)
初始化設(shè)置為-1的時(shí)候我們可以自己定義寫臨時(shí)文件規(guī)則誊爹,比如每讀1000行記錄flush到臨時(shí)一次蹬刷,可以大大減少磁盤IO次數(shù)。

7频丘、SXSSFWorkbook提供了一種低內(nèi)存占用的EXCEL導(dǎo)出方法办成,但是沒有提供讀取文件流的方法。因此讀入大數(shù)據(jù)量的時(shí)候還是只能使用XSSFWorkbook來讀取搂漠。

使用SAX模型來解析EXCEL不像DOM模型一下把所有文件內(nèi)容加載進(jìn)內(nèi)存诈火,它逐行掃描文檔,一邊掃描状答,一邊解析冷守。所以那些只需要單遍讀取內(nèi)容的應(yīng)用程序就可以從SAX解析中受益,這對(duì)大型文檔的解析是個(gè)巨大優(yōu)勢(shì)惊科。

OPCPackage pkg = OPCPackage.open(filename);
XSSFReader xssfReader = new XSSFReader(pkg);

POI Sax 事件驅(qū)動(dòng)解析Excel2007文件

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市馆截,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌蜡娶,老刑警劉巖混卵,帶你破解...
    沈念sama閱讀 218,451評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件幕随,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡赘淮,警方通過查閱死者的電腦和手機(jī)辕录,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,172評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來梢卸,“玉大人走诞,你說我怎么就攤上這事「蚋撸” “怎么了蚣旱?”我有些...
    開封第一講書人閱讀 164,782評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)戴陡。 經(jīng)常有香客問我姻锁,道長(zhǎng),這世上最難降的妖魔是什么猜欺? 我笑而不...
    開封第一講書人閱讀 58,709評(píng)論 1 294
  • 正文 為了忘掉前任位隶,我火速辦了婚禮,結(jié)果婚禮上开皿,老公的妹妹穿的比我還像新娘涧黄。我一直安慰自己,他們只是感情好赋荆,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,733評(píng)論 6 392
  • 文/花漫 我一把揭開白布笋妥。 她就那樣靜靜地躺著,像睡著了一般窄潭。 火紅的嫁衣襯著肌膚如雪春宣。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,578評(píng)論 1 305
  • 那天嫉你,我揣著相機(jī)與錄音月帝,去河邊找鬼。 笑死幽污,一個(gè)胖子當(dāng)著我的面吹牛嚷辅,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播距误,決...
    沈念sama閱讀 40,320評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼簸搞,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了准潭?” 一聲冷哼從身側(cè)響起趁俊,我...
    開封第一講書人閱讀 39,241評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎刑然,沒想到半個(gè)月后寺擂,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,686評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,878評(píng)論 3 336
  • 正文 我和宋清朗相戀三年沽讹,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片武鲁。...
    茶點(diǎn)故事閱讀 39,992評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡爽雄,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出沐鼠,到底是詐尸還是另有隱情挚瘟,我是刑警寧澤,帶...
    沈念sama閱讀 35,715評(píng)論 5 346
  • 正文 年R本政府宣布饲梭,位于F島的核電站,受9級(jí)特大地震影響订框,放射性物質(zhì)發(fā)生泄漏兜叨。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,336評(píng)論 3 330
  • 文/蒙蒙 一矛物、第九天 我趴在偏房一處隱蔽的房頂上張望跪但。 院中可真熱鬧,春花似錦忆首、人聲如沸被环。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,912評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽悴能。三九已至,卻和暖如春冯凹,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背宇姚。 一陣腳步聲響...
    開封第一講書人閱讀 33,040評(píng)論 1 270
  • 我被黑心中介騙來泰國(guó)打工浑劳, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人魔熏。 一個(gè)月前我還...
    沈念sama閱讀 48,173評(píng)論 3 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像镶骗,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子鼎姊,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,947評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容