存档解压缩/解压缩过程中的进度信息

时间:2018-03-11 13:29:49

标签: java commons-compress

目前我正在尝试在zip文件的解压缩过程中获取进度信息。

我深入研究了所有需要压缩/解压缩算法的commons-compress等,但是我所缺少的是以某种方式获取进度信息...在解压缩过程中为用户提供控制台等信息。我是否遗漏了什么?也许我还没有仔细阅读文档?

我已经通过使用java.util.Zip查看了一些内容,但是commons compress是一个支持不同格式的更通用的库......

1 个答案:

答案 0 :(得分:0)

跟踪输入读取字节数并将其与压缩文件大小进行比较,您可以获得解压缩进度的指示。

我将此类粘贴为解决方案的近似值,它使用包装器封装FileInputStream,该包装器跟踪读取大小并调用回调以在控制台中打印进度:

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.zip.GZIPInputStream;

public final class Gz {

    protected static interface GzProgress {

        public void progress(long read, long max);
    }

    protected static final class GzConsoleProgress implements GzProgress {

        protected final int incr;
        protected int lastPercent;

        protected GzConsoleProgress(int incr) {
            this.incr = incr;
            this.lastPercent = 0;
        }

        @Override
        public void progress(long read, long max) {
            final int percent = (int) (read * 100 / max);
            if (percent >= lastPercent + incr) {
                final int items = (percent - lastPercent) / incr;
                for (int i = 0; i < items; i++) {
                    System.out.print('#');
                }
                lastPercent = percent % incr == 0 ? percent : (percent - percent % incr);
            }
        }
    }

    protected static final class GzProgressInputStream extends BufferedInputStream {

        protected final long max;
        protected long read;
        protected final GzProgress progress;
        protected boolean end;

        protected GzProgressInputStream(InputStream is, long max, GzProgress progress) {
            super(is);
            this.max = max;
            this.read = 0;
            this.progress = progress;
            end = false;
        }

        @Override
        public synchronized int read(byte[] b, int off, int len) throws IOException {
            final int r = super.read(b, off, len);
            if (r > 0) {
                read += r;
                progress.progress(read, max);
                end = read == max;
            }
            return r;
        }

        @Override
        public void close() throws IOException {
            try {
                super.close();
            } finally {
                if (!end) {
                    progress.progress(max, max);
                }
            }
        }
    }

    public static void main(String[] args) {
        if (args == null || args.length == 0) {
            System.out.println("Usage: java " + Gz.class.getName() + " file1.gz file2.gz ...");
        } else {
            final int progressPercent = 10;
            for (final String filename : args) {
                final File file = new File(filename);
                if (file.exists() && filename.toLowerCase().endsWith(".gz")) {
                    final File outFile = new File(filename.replaceAll(".gz$", ""));
                    System.out.println("Extracting " + filename + " ...");
                    final long length = file.length();
                    try (final InputStream is = new GZIPInputStream(new GzProgressInputStream(new FileInputStream(file),
                            length, new GzConsoleProgress(progressPercent)));
                            final OutputStream os = new BufferedOutputStream(new FileOutputStream(outFile))) {
                        final byte[] buff = new byte[512];
                        int r = 0;
                        while ((r = (is.read(buff))) != -1) {
                            os.write(buff, 0, r);
                        }
                    } catch (final IOException e) {
                        System.err.println("Error extracting " + filename + ": " + e.getMessage());
                    }
                    System.out.println();
                }
            }
        }
    }
}

我希望能提供帮助。