欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java利用ZipOutputStream進(jìn)行高效壓縮的技巧詳解

 更新時間:2025年07月07日 08:14:35   作者:心之語歌  
ZipOutputStream 是 Java 標(biāo)準(zhǔn)庫中用于 創(chuàng)建 ZIP 文件 的核心類,位于 java.util.zip 包中,本文主要和大家介紹了Java如何使用ZipOutputStream進(jìn)行高效壓縮,有需要的可以了解下

簡介

ZipOutputStream 是 Java 標(biāo)準(zhǔn)庫中用于 創(chuàng)建 ZIP 文件 的核心類,位于 java.util.zip 包中。它允許你將多個文件或字節(jié)流寫入一個 ZIP 壓縮包,并支持設(shè)置壓縮級別、編碼方式等參數(shù)。

基本概念

ZipOutputStream的作用

  • 將多個文件(或字節(jié)數(shù)組)打包成一個 ZIP 文件。
  • 支持添加多個條目(ZipEntry),每個條目代表 ZIP 中的一個文件。
  • 可控制壓縮級別、編碼格式、注釋等。

常用方法說明

方法描述
putNextEntry(ZipEntry entry)開始寫入一個新的 ZIP 條目(文件)
closeEntry()關(guān)閉當(dāng)前 ZIP 條目,準(zhǔn)備寫入下一個
write(byte[] b, int off, int len)寫入當(dāng)前條目的內(nèi)容(字節(jié)數(shù)據(jù))
setLevel(int level)設(shè)置壓縮級別(0~9)
setComment(String comment)設(shè)置整個 ZIP 文件的注釋
finish()完成寫入,但不關(guān)閉底層輸出流(可選)

可選的壓縮級別(取值范圍:0 ~ 9)

級別含義特點(diǎn)
Deflater.NO_COMPRESSION (0)不壓縮速度最快,ZIP 文件最大
Deflater.BEST_SPEED (1)最快壓縮壓縮率低,速度快
Deflater.DEFAULT_COMPRESSION (6)默認(rèn)壓縮平衡壓縮率與速度
Deflater.BEST_COMPRESSION (9)最佳壓縮壓縮率最高,速度最慢

本地保存

import java.io.*;
import java.nio.file.*;
import java.util.zip.*;

public class ZipDemo {
    public static void main(String[] args) throws IOException {
        // 源文件夾路徑:要壓縮的文件所在的目錄
        String sourceDir = "path/to/folder";

        // 輸出 ZIP 文件路徑:生成的壓縮包保存的位置和名稱
        String zipFilePath = "output.zip";

        // 使用 try-with-resources 自動關(guān)閉資源(FileOutputStream 和 ZipOutputStream)
        try (FileOutputStream fos = new FileOutputStream(zipFilePath);
             ZipOutputStream zos = new ZipOutputStream(fos)) {

            // 設(shè)置 ZIP 壓縮級別為最佳壓縮(壓縮率最高,但速度較慢)
            zos.setLevel(Deflater.BEST_COMPRESSION);

            // 遍歷源目錄下的所有文件(包括子目錄中的文件)
            Files.walk(Paths.get(sourceDir))
                 // 過濾掉目錄,只保留文件
                 .filter(path -> !Files.isDirectory(path))
                 // 對每個文件執(zhí)行以下操作
                 .forEach(path -> {
                     try {
                         // 構(gòu)建相對路徑字符串:sourceDir + 文件分隔符 + 文件名
                         // 注意:這會導(dǎo)致 ZIP 中的路徑包含 sourceDir 的前綴
                         String relativePath = sourceDir + File.separator + path.getFileName();

                         // 創(chuàng)建一個 ZIP 條目(即 ZIP 包中的一個文件)
                         ZipEntry zipEntry = new ZipEntry(relativePath);

                         // 開始寫入該條目到 ZIP 流中
                         zos.putNextEntry(zipEntry);

                         // 讀取文件內(nèi)容為字節(jié)數(shù)組
                         byte[] bytes = Files.readAllBytes(path);

                         // 將文件內(nèi)容寫入 ZIP 輸出流
                         zos.write(bytes, 0, bytes.length);

                         // 關(guān)閉當(dāng)前 ZIP 條目,準(zhǔn)備寫入下一個文件
                         zos.closeEntry();

                     } catch (IOException e) {
                         // 如果寫入失敗,打印錯誤信息并輸出異常堆棧
                         System.err.println("寫入 ZIP 失敗: " + path);
                         e.printStackTrace();
                     }
                 });
        }
        // try-with-resources 會自動關(guān)閉 fos 和 zos,無需手動 close()
    }
}

ZIP 文件網(wǎng)絡(luò)流下載

response.setContentType("application/zip");
response.setHeader("Content-Disposition", "attachment; filename=\"streamed_files.zip\"");

try (ZipOutputStream zipOut = new ZipOutputStream(response.getOutputStream(), StandardCharsets.UTF_8)) {
    zipOut.setLevel(Deflater.BEST_SPEED);

    for (User u : userList) {
        String fileName = String.format("%sxxxx.docx", u.getNickName());

        try {
            zipOut.putNextEntry(new ZipEntry(fileName));
            byte[] docBytes = genDocx(u).toByteArray();
            zipOut.write(docBytes, 0, docBytes.length);
            zipOut.closeEntry();
        } catch (IOException e) {
            log.error("寫入 ZIP 條目失敗: {}", fileName, e);
            throw new IOException("生成 ZIP 條目時出錯: " + fileName, e);
        }
    }

} catch (IOException ex) {
    log.error("導(dǎo)出 ZIP 異常", ex);
    throw new RuntimeException("導(dǎo)出異常");
}

1. 設(shè)置響應(yīng)頭

response.setContentType("application/zip");
  • 設(shè)置 HTTP 響應(yīng)內(nèi)容類型為 application/zip,告訴瀏覽器這是一個 ZIP 文件。
  • 瀏覽器收到后會識別為壓縮文件,通常會觸發(fā)下載行為。
response.setHeader("Content-Disposition", "attachment; filename=\"streamed_files.zip\"");
  • 設(shè)置響應(yīng)頭 Content-Disposition,值為 attachment 表示讓瀏覽器不要在頁面中顯示該內(nèi)容,而是提示用戶下載。
  • filename="streamed_files.zip" 指定下載時的默認(rèn)文件名。

2. 創(chuàng)建 ZIP 輸出流(使用 try-with-resources)

try (ZipOutputStream zipOut = new ZipOutputStream(response.getOutputStream(), StandardCharsets.UTF_8)) {
  • 使用 try-with-resources 自動關(guān)閉資源,確保最后流會被正確關(guān)閉。
  • 創(chuàng)建了一個 ZipOutputStream,它是一個用于寫入 ZIP 文件格式的輸出流。
  • 第二個參數(shù) StandardCharsets.UTF_8 是為了支持中文文件名編碼(避免解壓時出現(xiàn)亂碼)。

注意:部分舊系統(tǒng)或工具(如 Windows 自帶解壓器)可能不識別 UTF-8 編碼的 ZIP 文件名,建議使用 7-Zip、WinRAR 或 Mac 解壓工具。

3. 設(shè)置壓縮級別(可選)

zipOut.setLevel(Deflater.BEST_SPEED);
  • 設(shè)置壓縮級別為最快壓縮模式。
  • 這樣可以減少服務(wù)器 CPU 占用,適合對壓縮率要求不高但希望快速響應(yīng)用戶的場景。
  • 可替換為:
    • Deflater.DEFAULT_COMPRESSION(默認(rèn))
    • Deflater.BEST_COMPRESSION(最佳壓縮)

4. 生成文件加入到 zip 流

zipOut.putNextEntry(new ZipEntry(fileName));
  • 在 ZIP 包中創(chuàng)建一個新的條目(即文件),名字是上面生成的文件名。
  • 每次調(diào)用 putNextEntry() 后必須調(diào)用 closeEntry() 才能繼續(xù)添加下一個文件。
byte[] docBytes = genDocx(u).toByteArray();
zipOut.write(docBytes, 0, docBytes.length);
  • 調(diào)用 genDocx(u) 方法生成當(dāng)前用戶的 .docx 文件內(nèi)容(返回的是 ByteArrayOutputStream)。
  • 將其轉(zhuǎn)為字節(jié)數(shù)組后寫入 ZIP 流中。
zipOut.closeEntry();

關(guān)閉當(dāng)前 ZIP 條目,準(zhǔn)備寫入下一個文件。

到此這篇關(guān)于Java利用ZipOutputStream進(jìn)行高效壓縮的技巧詳解的文章就介紹到這了,更多相關(guān)Java ZipOutputStream壓縮內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • SpringMVC工作原理實例詳解

    SpringMVC工作原理實例詳解

    這篇文章主要介紹了SpringMVC工作原理實例詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-03-03
  • Java中sort排序函數(shù)實例詳解

    Java中sort排序函數(shù)實例詳解

    我們經(jīng)常使用java中的sort排序,確實好用,但是其中原理大多數(shù)人都是不了解的,下面這篇文章主要給大家介紹了關(guān)于Java中sort排序函數(shù)的相關(guān)資料,文中通過實例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-06-06
  • Java ==,equals()與hashcode()的使用

    Java ==,equals()與hashcode()的使用

    本文主要介紹了Java ==,equals()與hashcode()的使用,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-05-05
  • spring boot 配置freemarker及如何使用freemarker渲染頁面

    spring boot 配置freemarker及如何使用freemarker渲染頁面

    springboot中自帶的頁面渲染工具為thymeleaf 還有freemarker這兩種模板引擎,本文重點(diǎn)給大家介紹spring boot 配置freemarker及如何使用freemarker渲染頁面,感興趣的朋友一起看看吧
    2023-10-10
  • Java類之間的關(guān)系圖_動力節(jié)點(diǎn)Java學(xué)院整理

    Java類之間的關(guān)系圖_動力節(jié)點(diǎn)Java學(xué)院整理

    在Java以及其他的面向?qū)ο笤O(shè)計模式中,類與類之間主要有6種關(guān)系,他們分別是:依賴、關(guān)聯(lián)、聚合、組合、繼承、實現(xiàn)。他們的耦合度依次增強(qiáng),有興趣的可以了解一下
    2017-08-08
  • 解決Springboot項目報錯:java:錯誤:不支持發(fā)行版本?17

    解決Springboot項目報錯:java:錯誤:不支持發(fā)行版本?17

    這篇文章主要給大家介紹了關(guān)于解決Springboot項目報錯:java:錯誤:不支持發(fā)行版本17的相關(guān)資料,這個錯誤意味著你的Spring Boot項目正在使用Java 17這個版本,但是你的項目中未配置正確的Java版本,需要的朋友可以參考下
    2023-08-08
  • 6種常見的SpringBoot攔截器使用場景及實現(xiàn)方式

    6種常見的SpringBoot攔截器使用場景及實現(xiàn)方式

    這篇文章主要為大家詳細(xì)介紹了SpringBoot中6種常見的攔截器使用場景及其實現(xiàn)方式,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2025-04-04
  • Mybatis批量新增的三種實現(xiàn)方式

    Mybatis批量新增的三種實現(xiàn)方式

    文章講述了在Java中進(jìn)行批量操作的最佳實踐,包括使用MyBatis的ExecutorType.BATCH模式,作者建議根據(jù)實際需求選擇是否進(jìn)行批量操作,因為批量操作并不總是能提升性能,且有副作用,如無法獲取自增ID等
    2024-12-12
  • springMVC詳細(xì)介紹

    springMVC詳細(xì)介紹

    下面小編就為大家?guī)硪黄赟pring MVC 詳細(xì)介紹。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2021-07-07
  • 淺談對象與Map相互轉(zhuǎn)化

    淺談對象與Map相互轉(zhuǎn)化

    這篇文章主要介紹了利用BeanMap進(jìn)行對象與Map的相互轉(zhuǎn)換,在文中列舉了完整代碼,需要的朋友可以參考下。
    2017-09-09

最新評論