当前位置:首页 > 后端开发 > 正文

文件压缩java怎么写

使用ZipOutputStream创建压缩流,遍历文件并写入压缩包,设置缓冲区,关闭

在Java中实现文件压缩主要依赖java.util.zip包或第三方库(如Apache Commons Compress),以下是详细的实现步骤、代码示例及注意事项,涵盖ZIP和GZIP两种常见压缩格式。

Java文件压缩基础

  1. 核心类库

    • ZipOutputStream/ZipInputStream:用于ZIP格式压缩与解压。
    • GZIPOutputStream/GZIPInputStream:用于GZIP格式压缩与解压。
    • FileInputStream/FileOutputStream:读写文件数据。
    • BufferedInputStream/BufferedOutputStream:提升读写效率。
  2. 压缩原理

    文件压缩java怎么写 第1张

    • ZIP支持多文件压缩,可保留目录结构;GZIP通常用于单文件压缩。
    • 压缩级别范围为0(无压缩)到9(最大压缩),需平衡压缩率与性能。

ZIP格式压缩实现

压缩单个文件

import java.io.; import java.util.zip.; public class FileCompressor { public static void zipSingleFile(String srcFile, String zipFile) throws IOException { try (FileOutputStream fos = new FileOutputStream(zipFile); ZipOutputStream zos = new ZipOutputStream(fos); FileInputStream fis = new FileInputStream(srcFile)) { ZipEntry entry = new ZipEntry(new File(srcFile).getName()); zos.putNextEntry(entry); byte[] buffer = new byte[4096]; int len; while ((len = fis.read(buffer)) > 0) { zos.write(buffer, 0, len); } } } }

关键点

  • 使用ZipEntry指定压缩文件的名称。
  • 通过缓冲区(byte[] buffer)提高读写效率。

压缩多个文件或目录

public static void zipDirectory(String srcDir, String zipFile) throws IOException { try (FileOutputStream fos = new FileOutputStream(zipFile); ZipOutputStream zos = new ZipOutputStream(fos)) { File file = new File(srcDir); compressFile(file, zos, ""); } } private static void compressFile(File file, ZipOutputStream zos, String parentPath) throws IOException { if (file.isDirectory()) { // 空目录需创建ZipEntry以保留结构 zos.putNextEntry(new ZipEntry(parentPath + "/")); zos.closeEntry(); for (File child : file.listFiles()) { compressFile(child, zos, parentPath + "/" + file.getName()); } } else { try (FileInputStream fis = new FileInputStream(file)) { ZipEntry entry = new ZipEntry(parentPath + "/" + file.getName()); zos.putNextEntry(entry); byte[] buffer = new byte[4096]; int len; while ((len = fis.read(buffer)) > 0) { zos.write(buffer, 0, len); } } } }

关键点

文件压缩java怎么写 第2张

  • 递归遍历目录,对空目录创建ZipEntry以保留层级结构。
  • 通过parentPath参数维护相对路径,避免绝对路径导致压缩包移植性差。

设置压缩级别与性能优化

zos.setLevel(Deflater.BEST_COMPRESSION); // 设置最高压缩级别

性能优化策略

| 优化方向 | 具体措施 |

|———-|———-|

| 缓冲区大小 | 使用byte[] buffer(建议4KB或更大)减少I/O次数 |

| 多线程压缩 | 对独立文件分配线程并行压缩,但需避免共享ZipOutputStream |

| 大文件分块 | 分段读取文件,避免内存溢出 |

GZIP格式压缩

GZIP适用于单文件压缩,不支持目录结构。

public static void gzipFile(String srcFile, String gzipFile) throws IOException { try (FileInputStream fis = new FileInputStream(srcFile); FileOutputStream fos = new FileOutputStream(gzipFile); GZIPOutputStream gos = new GZIPOutputStream(fos)) { byte[] buffer = new byte[4096]; int len; while ((len = fis.read(buffer)) > 0) { gos.write(buffer, 0, len); } } }

关键点

文件压缩java怎么写 第3张

  • GZIP自动处理压缩级别(默认中等),可通过GZIPOutputStream(fos, Deflater.BEST_COMPRESSION)自定义。

解压操作

解压ZIP文件

public static void unzipFile(String zipFile, String destDir) throws IOException { try (FileInputStream fis = new FileInputStream(zipFile); ZipInputStream zis = new ZipInputStream(fis)) { ZipEntry entry; while ((entry = zis.getNextEntry()) != null) { File file = new File(destDir, entry.getName()); if (entry.isDirectory()) { file.mkdirs(); } else { file.getParentFile().mkdirs(); try (FileOutputStream fos = new FileOutputStream(file)) { byte[] buffer = new byte[4096]; int len; while ((len = zis.read(buffer)) > 0) { fos.write(buffer, 0, len); } } } zis.closeEntry(); } } }

注意事项

  • 防止ZIP Slip漏洞(恶意路径穿透),需验证entry.getName()不包含等非法字符。

解压GZIP文件

public static void gunzipFile(String gzipFile, String outputFile) throws IOException { try (FileInputStream fis = new FileInputStream(gzipFile); GZIPInputStream gis = new GZIPInputStream(fis); FileOutputStream fos = new FileOutputStream(outputFile)) { byte[] buffer = new byte[4096]; int len; while ((len = gis.read(buffer)) > 0) { fos.write(buffer, 0, len); } } }

常见问题与解决方案

FAQs

Q1:如何设置压缩级别?

A1:通过ZipOutputStream.setLevel(int level)或GZIPOutputStream(OutputStream, int level)设置,值范围为0(无压缩)到9(最大压缩)。

Q2:中文文件名出现乱码如何解决?

A2:使用Apache Commons Compress库,并指定UTF-8编码:

ZipArchiveEntry entry = new ZipArchiveEntry(file.getName()); entry.setUnicodeExtra(true); // 启用UTF-8支持

或手动设置ZipEntry的注释字段存储原始文件名。

  • ZIP适合多文件压缩,保留目录结构;GZIP适合单文件压缩。
  • 性能优化需关注缓冲区、多线程及压缩级别。
  • 第三方库(如Apache Commons Compress)可解决编码、格式兼容等问题

0