Java中的压缩和解压缩

1.介绍

本篇文章介绍,如何将文件压缩到存档中以及如何解压存档——所有这些都使用 Java 提供的核心库。

这些核心库是 java.util.zip 包的一部分——可以在其中找到所有与压缩和解压缩相关的实用程序。

2.压缩文件

看一个简单的操作——压缩单个文件。

对于示例,将一个名为 test1.txt 的文件压缩到一个名为compressed.zip 的存档文件中。

@Test
    public  void test1() throws IOException {
    
    
        String sourceFile = "D:\\test1.txt";
        //compressed.zip没有将会自动创建
        FileOutputStream fos = new FileOutputStream("D:\\compressed.zip");
        ZipOutputStream zipOut = new ZipOutputStream(fos);
        File fileToZip = new File(sourceFile);
        FileInputStream fis = new FileInputStream(fileToZip);
        ZipEntry zipEntry = new ZipEntry(fileToZip.getName());
        zipOut.putNextEntry(zipEntry);
        byte[] bytes = new byte[1024];
        int length;
        while((length = fis.read(bytes)) >= 0) {
    
    
            zipOut.write(bytes, 0, length);
        }
        zipOut.close();
        fis.close();
        fos.close();
    }

3.压缩多个文件

如何将多个文件压缩成一个 zip 文件。 将 test1.txt 和 test2.txt 压缩成 multiCompressed.zip:

  @Test
    public void  test2() throws Exception {
    
    
        List<String> srcFiles = Arrays.asList("D:\\test1.txt", "D:\\test2.txt");
        FileOutputStream fos = new FileOutputStream("D:\\multiCompressed.zip");
        ZipOutputStream zipOut = new ZipOutputStream(fos);
        for (String srcFile : srcFiles) {
    
    
            File fileToZip = new File(srcFile);
            FileInputStream fis = new FileInputStream(fileToZip);
            ZipEntry zipEntry = new ZipEntry(fileToZip.getName());
            zipOut.putNextEntry(zipEntry);

            byte[] bytes = new byte[1024];
            int length;
            while((length = fis.read(bytes)) >= 0) {
    
    
                zipOut.write(bytes, 0, length);
            }
            fis.close();
        }
        zipOut.close();
        fos.close();
    }

4.压缩目录

接下来的示例演示,如何压缩整个目录。 将 zipTest 目录到 dirCompressed.zip :

    @Test
    public void test3() throws Exception {
    
    
        String sourceFile = "D:\\zipTest";
        FileOutputStream fos = new FileOutputStream("D:\\dirCompressed.zip");
        ZipOutputStream zipOut = new ZipOutputStream(fos);
        File fileToZip = new File(sourceFile);

        zipFile(fileToZip, fileToZip.getName(), zipOut);
        zipOut.close();
        fos.close();
    }

    private  void zipFile(File fileToZip, String fileName, ZipOutputStream zipOut) throws IOException {
    
    
        if (fileToZip.isHidden()) {
    
    
            return;
        }
        if (fileToZip.isDirectory()) {
    
    
            if (fileName.endsWith("/")) {
    
    
                zipOut.putNextEntry(new ZipEntry(fileName));
                zipOut.closeEntry();
            } else {
    
    
                zipOut.putNextEntry(new ZipEntry(fileName + "/"));
                zipOut.closeEntry();
            }
            File[] children = fileToZip.listFiles();
            for (File childFile : children) {
    
    
                zipFile(childFile, fileName + "/" + childFile.getName(), zipOut);
            }
            return;
        }
        FileInputStream fis = new FileInputStream(fileToZip);
        ZipEntry zipEntry = new ZipEntry(fileName);
        zipOut.putNextEntry(zipEntry);
        byte[] bytes = new byte[1024];
        int length;
        while ((length = fis.read(bytes)) >= 0) {
    
    
            zipOut.write(bytes, 0, length);
        }
        fis.close();
    }

注意:

  • 为了压缩子目录,递归地遍历它们。
  • 每次找到目录时,我们将其名称附加到后代 ZipEntry 名称以保存层次结构。
  • 还要为每个空目录创建一个目录条目

5.解压缩文档

现在解压缩档案并提取其内容。

以下演示实例,把compressed.zip 解压缩到一个名为unzipTest 的新文件夹中。

public class UnzipFile {
    
    
    public static void main(String[] args) throws IOException {
    
    
        String fileZip = "D://compressed.zip";
        File destDir = new File("E://unzipTest");
        byte[] buffer = new byte[1024];
        ZipInputStream zis = new ZipInputStream(new FileInputStream(fileZip));
        ZipEntry zipEntry = zis.getNextEntry();
        while (zipEntry != null) {
    
    
            File newFile = newFile(destDir, zipEntry);
            if (zipEntry.isDirectory()) {
    
    
                if (!newFile.isDirectory() && !newFile.mkdirs()) {
    
    
                    throw new IOException("创建目录失败: " + newFile);
                }
            } else {
    
    
                //修复 Windows 创建的目录
                File parent = newFile.getParentFile();
                if (!parent.isDirectory() && !parent.mkdirs()) {
    
    
                    throw new IOException("创建目录失败: " + parent);
                }
                
                FileOutputStream fos = new FileOutputStream(newFile);
                int len;
                while ((len = zis.read(buffer)) > 0) {
    
    
                    fos.write(buffer, 0, len);
                }
                fos.close();
            }
            zipEntry = zis.getNextEntry();
        }
        zis.closeEntry();
        zis.close();
    }

    public static File newFile(File destinationDir, ZipEntry zipEntry) throws IOException {
    
    
        File destFile = new File(destinationDir, zipEntry.getName());

        String destDirPath = destinationDir.getCanonicalPath();
        String destFilePath = destFile.getCanonicalPath();

        if (!destFilePath.startsWith(destDirPath + File.separator)) {
    
    
            throw new IOException("文件在目标目录之外: " + zipEntry.getName());
        }

        return destFile;
    }
}
  • 在 while 循环中,遍历每个 ZipEntry 并首先检查它是否是一个目录。 如果是,将使用 mkdirs() 方法创建目录; 否则,继续创建文件:
  • 这里需要注意的是,在 else 分支上,首先检查文件的父目录是否存在。 这对于在 Windows 上创建的档案是必需的,其中根目录在 zip 文件中没有相应的条目。

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/niugang0920/article/details/120621683