最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java使用FileOutputStream寫Excel文件不落盤的解決方法

 更新時間:2025年11月03日 09:21:47   投稿:bairu  
最近在寫 Java 代碼處理 Excel 文件的時候,遇到了一個挺頭疼的問題:使用 Apache POI 的 XSSFWorkbook.write(FileOutputStream) 方法寫文件,生成的 Excel 文件卻打不開,所以本文就給大家介紹了Java使用FileOutputStream寫Excel文件不落盤的解決方法

引言

最近在寫 Java 代碼處理 Excel 文件的時候,遇到了一個挺頭疼的問題:使用 Apache POI 的 XSSFWorkbook.write(FileOutputStream) 方法寫文件,代碼執(zhí)行得好好的,也沒有拋出異常,但生成的 Excel 文件卻打不開,甚至有時候文件大小還是 0 字節(jié),一點數(shù)據(jù)都沒有。

本來以為是 POI 的問題,結(jié)果查了一圈文檔才發(fā)現(xiàn)——鍋還真不在 POI,而是我自己對文件輸出流的使用方式不太對,尤其是涉及到 FileOutputStream 的時候,有些隱藏的“坑”沒注意到。

這篇文章就把我踩坑的過程整理一下,順便聊聊 Java 中如何正確地使用輸出流寫 Excel 文件,避免“寫了但沒落盤”的問題。

1. FileOutputStream 本身是沒有緩沖

我們先來看看一個最常見的代碼片段:

Workbook workbook = new XSSFWorkbook(inputStream);
workbook.write(new FileOutputStream("output.xlsx"));

這樣寫看起來挺順,但你知道嗎?這里的 FileOutputStream 直接把數(shù)據(jù)寫到操作系統(tǒng)的,沒有中間的緩沖區(qū)。如果你的數(shù)據(jù)量很大,比如幾百 KB,甚至幾 MB,雖然代碼沒報錯,但你可能會發(fā)現(xiàn)文件根本沒寫完整,或者干脆就是個空殼文件。

為什么?

因為操作系統(tǒng)本身還會有一個寫入緩沖區(qū)(Page Cache),你并不能保證調(diào)用了 write() 之后,數(shù)據(jù)就馬上穩(wěn)穩(wěn)當(dāng)當(dāng)?shù)芈涞搅舜疟P上。如果你沒有關(guān)閉輸出流或者手動調(diào)用 flush(),這些數(shù)據(jù)可能就一直在內(nèi)存里排隊,根本沒真正寫進(jìn)文件。

2. 沒有 flush() 或 close(),數(shù)據(jù)可能永遠(yuǎn)不會寫進(jìn)硬盤

這是很多人常犯的一個錯誤??瓷先ゴa沒問題,但一旦你漏掉了 flush() 或者 close(),就會導(dǎo)致寫入的數(shù)據(jù)停留在緩沖區(qū)里,始終不落盤。

比如下面這段代碼就是“反面教材”:

FileOutputStream fos = new FileOutputStream("output.xlsx");
workbook.write(fos);
// 沒有 fos.flush()
// 沒有 fos.close()

你以為 write() 就完事了,其實根本沒有。解決方案很簡單,要么在寫完之后手動調(diào)用:

fos.flush();
fos.close();

要么——更推薦的方式是使用 try-with-resources 來自動幫你處理這些關(guān)閉操作。

3. 用 BufferedOutputStream 包裝一下,寫得更穩(wěn)也更快

前面說了,F(xiàn)ileOutputStream 是沒有緩沖的,這意味著它每調(diào)用一次 write() 就是一次底層系統(tǒng)調(diào)用,效率其實挺低的,尤其是在 Apache POI 這種寫 Excel 文件會反復(fù)調(diào)用 write() 的場景下。

所以非常推薦你用 BufferedOutputStream 包一下:

OutputStream bos = new BufferedOutputStream(new FileOutputStream("output.xlsx"));
workbook.write(bos);
bos.flush();
bos.close();

多一層緩沖不僅能提升寫入速度,更重要的是減少系統(tǒng)調(diào)用的頻率,能讓寫入過程更加穩(wěn)定可靠。

4. 推薦用法:try-with-resources,優(yōu)雅又安全

說了這么多,其實最靠譜、最簡單、最不容易出錯的寫法,還是 Java 7 引入的 try-with-resources。

你只要這么寫:

try (
    InputStream inputStream = new FileInputStream("template.xlsx");
    Workbook workbook = new XSSFWorkbook(inputStream);
    OutputStream outputStream = new BufferedOutputStream(new FileOutputStream("output.xlsx"))
) {
    workbook.write(outputStream);
}

Java 會自動幫你在塊結(jié)束后關(guān)閉 inputStream、workbook 和 outputStream,再也不用擔(dān)心忘了 flush()close() 了,簡直不要太爽。

5. 如果你就是不想用 try-with-resources,也請手動關(guān)閉資源

當(dāng)然,也不是所有項目都能用上 Java 7 及以上版本的語法,博主前些時間就接到了一個Java 6的項目咨詢,還真不是,你發(fā)任你發(fā),我用Java 8。哈哈,有些老項目沒法用 try-with-resources。那也不是不能寫,你只要自己負(fù)責(zé)把所有資源都在 finally 中手動關(guān)閉,也一樣可以穩(wěn)穩(wěn)落盤。

注意關(guān)閉的順序要搞對,先關(guān) workbook,再關(guān)輸出流。

示例如下:

Workbook workbook = null;
BufferedOutputStream bos = null;
 
try {
    workbook = new XSSFWorkbook();
    bos = new BufferedOutputStream(new FileOutputStream("output.xlsx"));
 
    workbook.write(bos);
    bos.flush();
 
} catch (Exception e) {
    e.printStackTrace();
} finally {
    try {
        if (workbook != null) workbook.close();
        if (bos != null) bos.close(); // close 會自動 flush
    } catch (IOException e) {
        e.printStackTrace();
    }
}

記?。篶lose() 會自動調(diào)用 flush(),但你也可以顯式加一遍 flush(),確保保險。

大 Excel 文件時內(nèi)存溢出風(fēng)險

  • XSSFWorkbook 加載整個 .xlsx 到內(nèi)存;
  • 寫入也可能消耗大量內(nèi)存;
  • 超過幾十萬行時可能拋出 OOM。

大數(shù)據(jù)量推薦使用 SXSSFWorkbook:

SXSSFWorkbook sxssfWorkbook = new SXSSFWorkbook((XSSFWorkbook) workbook); 
sxssfWorkbook.write(outputStream);
sxssfWorkbook.dispose(); // 清理臨時文件

6. 工作簿數(shù)據(jù)本身也別忘了檢查

最后還有一個冷門但真實的情況是——你其實根本就沒有往 Workbook 里寫任何東西。這樣寫出來的 Excel 文件雖然也是合法的 .xlsx,但打開后是空白頁,或者打開報錯,看上去像是“沒寫進(jìn)去”,其實是你沒寫進(jìn)去數(shù)據(jù)……

你可以加個調(diào)試代碼確認(rèn):

log.info("sheet count: {}", workbook.getNumberOfSheets());

7. 防止“寫了但沒落盤”的幾點 checklist

檢查項建議
使用緩沖流BufferedOutputStream 性能更穩(wěn)
手動或自動關(guān)閉flush() + close 必不可少
優(yōu)先使用 try-with-resources推薦寫法,防忘關(guān)
大文件用 SXSSFWorkbook防止內(nèi)存溢出
確認(rèn)實際寫入數(shù)據(jù)不要生成空文件

以上就是Java使用FileOutputStream寫Excel文件不落盤的解決方法的詳細(xì)內(nèi)容,更多關(guān)于Java FileOutputStream寫Excel文件的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Mybatis之RowBounds分頁原理詳解

    Mybatis之RowBounds分頁原理詳解

    這篇文章主要介紹了Mybatis之RowBounds分頁原理詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-02-02
  • SpringBoot+Mybatis使用Mapper接口注冊的幾種方式

    SpringBoot+Mybatis使用Mapper接口注冊的幾種方式

    本篇博文中主要介紹是Mapper接口與對應(yīng)的xml文件如何關(guān)聯(lián)的幾種姿勢,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-07-07
  • 淺談java中BigDecimal類的簡單用法

    淺談java中BigDecimal類的簡單用法

    這篇文章主要介紹了淺談java中BigDecimal類的簡單用法,在開發(fā)時,如果我們需要精確計算的結(jié)果,必須使用BigDecimal類來操作。感興趣的話可以了解一下
    2020-07-07
  • Java類變量和成員變量初始化過程的應(yīng)用介紹

    Java類變量和成員變量初始化過程的應(yīng)用介紹

    昨天看了一本叫做《突破程序員基本功的16課》的書,個人感覺還可以,主要對Java的技巧進(jìn)行了一些深入的講解,讓我對類的初始化和對象的創(chuàng)建有了新的認(rèn)識
    2013-04-04
  • java selenium處理Iframe中的元素示例

    java selenium處理Iframe中的元素示例

    本文主要介紹java selenium處理Iframe中的元素,這里整理了相關(guān)資料并附有示例代碼和實現(xiàn)方法,有需要的小伙伴可以參考下
    2016-08-08
  • mybatis-plus分頁查詢的實現(xiàn)實例

    mybatis-plus分頁查詢的實現(xiàn)實例

    頁查詢是一項常用的數(shù)據(jù)庫查詢方法,本文主要介紹了mybatis-plus分頁查詢的實現(xiàn)實例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2024-06-06
  • java 計算中位數(shù)的實現(xiàn)方法

    java 計算中位數(shù)的實現(xiàn)方法

    這篇文章主要介紹了java 計算中位數(shù)的實現(xiàn)方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-08-08
  • RabbitMQ下載與安裝教程

    RabbitMQ下載與安裝教程

    RabbitMQ是實現(xiàn)了高級消息隊列協(xié)議(AMQP)的開源消息代理軟件(亦稱面向消息的中間件),這篇文章給大家介紹RabbitMQ下載與安裝教程,感興趣的朋友跟隨小編一起看看吧
    2024-02-02
  • Java8 stream 中利用 groupingBy 進(jìn)行多字段分組求和案例

    Java8 stream 中利用 groupingBy 進(jìn)行多字段分組求和案例

    這篇文章主要介紹了Java8 stream 中利用 groupingBy 進(jìn)行多字段分組求和案例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-08-08
  • Spring AOP切點表達(dá)式使用及說明

    Spring AOP切點表達(dá)式使用及說明

    這篇文章主要介紹了Spring AOP切點表達(dá)式使用及說明,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-05-05

最新評論

连南| 乃东县| 连平县| 汽车| 海宁市| 武隆县| 浦县| 白朗县| 瑞丽市| 台南县| 杭州市| 英山县| 万源市| 云霄县| 油尖旺区| 进贤县| 扶沟县| 什邡市| 芦溪县| 鄂尔多斯市| 康平县| 江孜县| 缙云县| 广平县| 绵竹市| 呼和浩特市| 中方县| 连江县| 大理市| 蛟河市| 商城县| 南靖县| 昭觉县| 台东市| 讷河市| 武陟县| 永胜县| 芜湖市| 孝昌县| 蕉岭县| 五河县|