SoFunction
Updated on 2025-05-20

Sample code for implementing multi-level zip decompression in java

Preface

It is occasionally needed in the project, hoping to handle nested compressed packages, but not decompress files. I didn't want to re-create the wheels, but I didn't find any ready-made cases that were useful, so I simply dealt with them.

text

Java is generally used to decompress zipZipFile​ OrZipInputStream​。

In actual use, I encountered an error that could not be read by the zip manifest attribute, and finally used apache's ZipArchiveInputStream. MainlyallowStoredEntriesWithDataDescriptor​Properties.

The dependencies for the complete use of the code are as follows:

	    <dependency>
	      <groupId></groupId>
	      <artifactId>commons-compress</artifactId>
	      <version>1.19</version>
	    </dependency>
        <dependency>
            <groupId></groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.8.26</version>
        </dependency>
        <dependency>
            <groupId></groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.26</version>
        </dependency>

The code is mainly written to meet business needs and is relatively simple. Supports single decompression and recursive decompression, both returning buffered streams (buffered streams that cannot be closed) through callbacks.

It must be noted that ZipArchiveInputStream must not be closed in advance. This stream will be filled again after getNextZipEntry.

If the callback is adopted, the pressure on memory may be relatively high, so the data is returned through the buffered stream. To prevent accidental closing of flows in multiple collaborations, use a buffered flow tool that does not close the source flow.

If you need to decompress the specified package, you can do it by joining a filter.

Complete code example

package xxx;
import ;
import ;
import ;
/**
 Buffered stream for auxiliary not closing the original stream
 */
public class NoCloseBufferStream extends BufferedInputStream {
public NoCloseBufferStream(InputStream in) {
super(in);
}
@Override
public void close() throws IOException {
//The original stream will not be closed without implementing anything}
}
package xxx; //your package
 
import ;
import ;
import .slf4j.Slf4j;
import ;
import ;
 
import ;
import ;
import ;
import ;
import ;
 
/**
  * Note: The initial input stream will not be closed automatically
  *
  * @author Tieliu
  */
@Slf4j
public class UnZipUtil {
 
    public static void main(String[] args) throws IOException {
 
        try (InputStream inputStream = (new File("/Users/tieliu/Desktop/test/").toPath());) {
            loopUnzip(inputStream, (level, path, basePath, is) -&gt; {
                ();
                (" level: {},path: {},basePath: {}", level, path, basePath);
                return true;
            });
        }
    }
 
    /**
      * Recursively decompress zip, only compressed files with zip suffix name
      *
      * @param inputStream Initial file input stream
      * @param loopCallBack Recursive callback, return value controls whether to recurse downwards
      * @throws IOException File Streaming Exception
      */
    public static void loopUnzip(InputStream inputStream, LoopCallBack loopCallBack) throws IOException {
        loopUnzip(inputStream, 0, "", loopCallBack);
    }
 
    private static void loopUnzip(InputStream inputStream, int level, String basePath, LoopCallBack loopCallBack) throws IOException {
        decompress(inputStream, (path, is) -&gt; {
            // Here we decide whether to continue downward            if ((level, path, basePath, is) &amp;&amp; (".zip")) {
                loopUnzip(is, level + 1, basePath + "/" + path, loopCallBack);
            }
        });
    }
 
    /**
      * To unzip zip, it must be a file ending with zip (the file with the wrong attribute will be excluded, because Java cannot be unzipped if not ruled out)
      *
      * @param inputStream Initial input stream
      * @param callBack callback
      * @throws IOException io exception
      */
    public static void decompress(InputStream inputStream, CallBack callBack) throws IOException {
        try (NoCloseBufferStream bufferedInputStream = new NoCloseBufferStream(inputStream);
             ZipArchiveInputStream zipInputStream = new ZipArchiveInputStream(bufferedInputStream, ().name(), true, true)) {
            decompress(zipInputStream, callBack);
        }
    }
 
    public static void decompress(byte[] bytes, CallBack callBack) throws IOException {
        try (ByteArrayInputStream inputStream = (bytes);) {
            bytes = null;
            decompress(inputStream, callBack);
        }
    }
 
    private static void decompress(ZipArchiveInputStream inputStream, CallBack callBack) throws IOException {
        ZipArchiveEntry nextEntry = ();
        while (nextEntry != null) {
            final String name = ();
            //Filter useless files            if (!("__MACOSX") &amp;&amp; !(".DS_Store") &amp;&amp; !("") &amp;&amp; !("._")) {
                if (!()) {
                    (name, new NoCloseBufferStream(inputStream));
                }
            }
            nextEntry = ();
        }
    }
 
    @FunctionalInterface
    public static interface CallBack {
        void call(String relativePath, InputStream is) throws IOException;
    }
 
    @FunctionalInterface
    public static interface LoopCallBack {
        boolean call(int level, String relativePath, String basePath, InputStream is) throws IOException;
    }
 
}

This is the article about Java's example code to implement multi-level zip decompression. For more related java zip decompression, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!