Monitor GZip Download Progress in Java

download, gzip, java, monitor, progress

Solution

According to the specification, `GZIPInputStream` is a subclass of `InflaterInputStream`. `InflaterInputStream` has a `protected Inflater inf` field that is the `Inflater` used for the decompression work. `Inflater.getBytesRead` should be particularly useful for your purposes.

Unfortunately, `GZIPInputStream` does not expose `inf`, so probably you'll have to create your own subclass and expose the `Inflater`, e.g.

public final class ExposedGZIPInputStream extends GZIPInputStream {

  public ExposedGZIPInputStream(final InputStream stream) {
    super(stream);
  }

  public ExposedGZIPInputStream(final InputStream stream, final int n) {
    super(stream, n);
  }

  public Inflater inflater() {
    return super.inf;
  }
}
...
final ExposedGZIPInputStream gzip = new ExposedGZIPInputStream(...);
...
final Inflater inflater = gzip.inflater();
final long read = inflater.getBytesRead();

Problem

I download some files in my java app and implemented a download monitor dialog. But recently I compressed all the files with gzip and now the download monitor is kind of broken. I open the file as a `GZIPInputStream` and update the download status after every kB downloaded. If the file has a size of 1MB the progress goes up to e.g. 4MB which is the uncompressed size. I want to monitor the compressed download progress. Is this possible? EDIT: To clarify: I'm reading the bytes from the GZipInputStream which are the uncompressed bytes. So that does not give me the right filesize at the end. Here is my code: ``` URL url = new URL(urlString); HttpURLConnection con = (HttpURLConnection) url.openConnection(); con.connect(); ... File file = new File("bibles/" + name + ".xml"); if(!file.exists()) file.createNewFile(); out = new FileOutputStream(file); in = new BufferedInputStream(new GZIPInputStream(con.getInputStream())); byte[] buffer = new byte[1024]; int count; while((count = in.read(buffer)) != -1) { out.write(buffer, 0, count); downloaded += count; this.stateChanged(); } ... private void stateChanged() { this.setChanged(); this.notifyObservers(); } ``` Thanks for any help!

Original source