java实现zip文件解压缩教程

说明

最近开发有将文件打包成zip文件的需求,以供浏览器直接点击下载。这里可以使用JDK提供的相关方法,也可以使用第三方commons-compress提供的相关方法,这里需要注意的是以下几点:

  1. 需要满足可以压缩文件也可以是文件夹的需求。
  2. 压缩的时候能满足多级目录的需求。
  3. 空文件夹如需保存需特殊指明,否则空文件夹并不会进行压缩。
  4. 对于任何一个错误的文件路径,其默认类型为文件夹类型。

JDK方法解压缩

在解压缩文件中,使用到的JDK相关类如下所示:

import java.util.zip.Deflater;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;

可以使用java.util.zip包中的Deflater类常量可以指定压缩级别,这些常数是如下图所示:

ZipEntry对象表示Zip文件格式的归档文件中的条目,ZipInputStreamZipOutputStream是读取zip文件的输入、输出流。下面将演示如何解压缩zip文件。

  • 压缩文件
 /**
     * 压缩文件
     * @param zos 输出流1
     * @param file 压缩的文件对象
     */
    public static void compressZipFile(ZipOutputStream zos, File file) {
        File[] files = file.listFiles();
        try {
            if (file.isFile()) {
                writeZipEntry(zos, file);
            } else {
                // 空文件夹
                if (files.length == 0) {
                    ZipEntry zipEntry = new ZipEntry(file.getPath() + File.separator);
                    zos.putNextEntry(zipEntry);
                    zos.closeEntry();
                }
                // 递归调用
                for (File f : files) {
                    compressZipFile(zos, f);
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    /**
     * 写zip entry对象
     * @param zos
     * @param f
     */
    private static void writeZipEntry(ZipOutputStream zos, File f) {
        BufferedInputStream bis = null;
        try {
            ZipEntry zipEntry = new ZipEntry(f.getPath());
            zos.putNextEntry(zipEntry);
            bis = new BufferedInputStream(new FileInputStream(f));
            int len;
            byte[] bytes = new byte[1024];
            while ((len = bis.read(bytes)) != -1) {
                zos.write(bytes, 0, len);
            }
            zos.closeEntry();
            bis.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
 
  • 解压文件
 /**
     * 解压文件夹
     * @param zis 输入流
     * @param path 解压到path路径下
     */
    public static void deCompressZipFile(ZipInputStream zis, String path) {
        ZipEntry zipEntry = null;
        try {
            while ((zipEntry = zis.getNextEntry()) != null) {
                File file = new File(path + File.separator + zipEntry.getName());

                // 如果目录不存在就创建
                File parentFile = file.getParentFile();
                if (!parentFile.exists()) {
                    parentFile.mkdirs();
                }
                if (!zipEntry.isDirectory()) {
                    // 读取Entry对象

                    BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file));
                    byte[] bytes = new byte[1024];
                    int len;
                    while ((len = zis.read(bytes)) != -1) {
                        bos.write(bytes, 0, len);
                    }
                    bos.close();
                } else {
                    file.mkdirs();
                }

            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

测试执行

public static void main(String[] args) throws IOException {
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入压缩的文件目录");
        String line = scanner.nextLine().trim();
        File file = new File(line);
        if (!file.exists()) {
            System.out.println("输入的路径不合法");
            return;
        }
        File zipFile = new File("test.zip");

        ZipOutputStream zos = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(zipFile)));
        zos.setLevel(Deflater.BEST_COMPRESSION);
        // 压缩文件
        compressZipFile(zos, file);
        zos.close();
        File f = new File("test.zip");
        ZipInputStream zis = new ZipInputStream(new BufferedInputStream(new FileInputStream(f)));
        // 解压zip
        deCompressZipFile(zis, f.getAbsolutePath().replaceAll(File.separator + f.getName(), ""));
        zis.close();
    }

commons-compress解压缩

首先引入相关pom依赖如下所示:

        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.3</version>
        </dependency>

        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-compress</artifactId>
            <version>1.18</version>
        </dependency>

commons-compress是Apache开源组织提供的用于压缩解压的工具包,其可以支持以下文件格式的文件解压缩,如下图所示:

下面演示如何解压缩。

  • 压缩文件
 /**
     *
     * @param srcPath 原文件路径
     * @param destFile 压缩文件路径
     */
    public static void zipFile(String srcPath, String destFile) {
        File outFile = new File(destFile);
        FileOutputStream fos = null;
        BufferedOutputStream bufferedOutputStream = null;
        ArchiveOutputStream out = null;
        try {
            if (!outFile.exists()) {
                outFile.createNewFile();
            }
            fos = new FileOutputStream(outFile);
            bufferedOutputStream = new BufferedOutputStream(fos);
            out = new ArchiveStreamFactory().createArchiveOutputStream(
                    ArchiveStreamFactory.ZIP, bufferedOutputStream);

            if (srcPath.charAt(srcPath.length() - 1) != '/') {
                srcPath += '/';
            }
            File f = new File(srcPath);
            // 如果是文件夹
            if(f.isDirectory()) {
                Iterator<File> files = FileUtils.iterateFiles(f,
                        null, true);
                System.out.println(f.getAbsolutePath());
                while (files.hasNext()) {
                    File file = files.next();
                    writeEntry(srcPath, out, file);
                }
            } else {
                writeEntry(srcPath, out, f);
            }

            out.finish();
            out.close();
            bufferedOutputStream.close();
            fos.close();
        } catch (IOException e) {
            e.printStackTrace();

        } catch (ArchiveException e) {
            e.printStackTrace();
        } finally {
            try {
                if (out != null) {
                    out.close();
                }
                if (bufferedOutputStream != null) {
                    bufferedOutputStream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    private static void writeEntry(String srcPath, ArchiveOutputStream out, File file) throws IOException {
        ZipArchiveEntry zipArchiveEntry = new ZipArchiveEntry(file,
                file.getPath().replace(srcPath.replace("/", "\\"), ""));

        out.putArchiveEntry(zipArchiveEntry);
        IOUtils.copy(new FileInputStream(file), out);
        out.closeArchiveEntry();
    }
  • 解压文件
public static void deCompressZip(String zipPath) throws Exception
   {
      InputStream stream = new FileInputStream(zipPath);
      ZipArchiveInputStream inputStream = new ZipArchiveInputStream(stream);
      ZipArchiveEntry entry = null;
      while ((entry = inputStream.getNextZipEntry()) != null)
      {
         System.out.println(entry.getName());
         ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
         //读取内容
         IOUtils.copy(inputStream, outputStream);
         System.out.println(outputStream.toString());
      }
      inputStream.close();
      stream.close();
   }

猜你喜欢

转载自blog.csdn.net/javaee_gao/article/details/103545108