java 中的压缩和解压缩——20210929

java 项目总是有上传 zip 包和下载 zip 包的需求,这时就得用 ZipInputStream 和 ZipOutputStream 类。

基础概念

  1. ZipOutputStream:是一种 FilterInputStream 、装饰器模式中的实现类,它可以直接读取zip 包的内容

    1. ZipOutputStream (OutputStream out):zip 输出流
    2. ZipEntry(String name):表示压缩文件中的一个文件或者目录
    3. void putNextEntry(ZipEntry e):写入新的压缩文件或者目录
  2. ZipIutputStream:是一种 FilterOutputStream, 可以实现 zip 文件的解压

    1. ZipIutputStream (IutputStream out):zip 输入流
    2. ZipEntry getNextEntry():得到压缩文件中的一个文件或者目录

压缩

压缩文件就是先读取一个文件夹的内容,创建 ZipEntry 放入 ZipOutputStream 下,然后用 InputStream 读取源文件内容并写入 ZipOutputStream。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
/**
    * 压缩文件
    * @param sourceFilePath 待压缩的文件路径
    * @param zipFilePath    压缩后存放路径
    * @return
    */
public static void zip(String sourceFilePath, String zipFilePath) {
    File sourceFile = new File(sourceFilePath);

    if (!sourceFile.exists()) {
        System.out.println(sourceFilePath + " 不存在");
        return;
    }
    File zipFile = new File(zipFilePath);
    if (zipFile.exists()) {
        System.out.println(zipFilePath + " 已经存在");
        return;
    }

    try {
        byte[] buffer = new byte[1024];
        try (ZipOutputStream zos = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(zipFile)))){

            for(File file: sourceFile.listFiles()) {
                // 创建 ZIP 中的文件,并添加进压缩包
                ZipEntry zipEntry = new ZipEntry(file.getName());
                zos.putNextEntry(zipEntry);

                // 读取待压缩的文件并写进压缩包里
                try (InputStream bis = new BufferedInputStream(new FileInputStream(file))){
                    int read = 0;
                    while ((read = bis.read(buffer)) != -1) {
                        zos.write(buffer, 0, read);
                    }
                }
            }
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}

解压

一个压缩文件就是一个特殊的 File 叫做 ZipFile,用 Enumeration 类取出 zip 文件中被压缩的文件。

1
2
3
4
5
6
7
8
9
10
11
12
13
List<String> fileNames=new ArrayList<>();
try{
    ZipFile zipFile=new ZipFile(path, Charset.forName("gbk"));
    
    Enumeration<? extends ZipEntry> entries = zipFile.entries();
    while(entries.hasMoreElements()){
        String fileName=entries.nextElement().getName();
        fileNames.add(fileName);
        System.out.println("文件名称: "+fileName);
    }
}catch (Exception  e){
    e.printStackTrace();
}

解压文件 就是先用 zipFile.entries() 读取压缩文件夹中的文件, 生成 InputStream 流后写入被解压的 输出流

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
 /**
     * 解压
     * @param zipPath zip 文件夹路径
     * @param targetPath 解压路径
     */
    public static void unzip(String zipPath,String targetPath){

        File pathFile = new File(targetPath);
        if(!pathFile.exists()){
            pathFile.mkdirs();
        }

        try{
            //指定编码
            try(ZipFile zipFile = new ZipFile(zipPath, Charset.forName("gbk"))) {
                //遍历里面的文件及文件夹
                Enumeration entries = zipFile.entries();
                while (entries.hasMoreElements()) {
                    ZipEntry entry = (ZipEntry) entries.nextElement();
                    String zipEntryName = entry.getName();

                    try (InputStream in = zipFile.getInputStream(entry)) {
                        String outpath = (targetPath + File.separator + zipEntryName);
                        //判断路径是否存在,不存在则创建文件路径
                        File file = new File(outpath.substring(0, outpath.lastIndexOf(File.separator)));
                        if (!file.exists()) {
                            file.mkdirs();
                        }
                        //判断文件全路径是否为文件夹
                        if (new File(outpath).isDirectory())
                            continue;

                        try (OutputStream out = new FileOutputStream(outpath)) {
                            byte[] buffer = new byte[1024];
                            int len;
                            while ((len = in.read(buffer)) > 0) {
                                out.write(buffer, 0, len);
                            }
                        }
                    }
                }
            }
        }catch ( Exception e){
            e.printStackTrace();
        }
    }

总结

介绍了一下 java 中的压缩文件是如何解压与压缩的,对小伙伴们有帮助的话就点个赞哦。

示例代码:https://github.com/javatechnorth/java-north-sample/blob/master/zip/zipDemo.java

Java Geek Tech wechat
欢迎订阅 Java 技术指北,这里分享关于 Java 的一切。