On the bug of GZIPInputStream

Keywords: Java REST IE JDK

http://cin-ie.iteye.com/blog/859822

As for the bug of GZIPInputStream, this problem has not been solved in the latest version of jdk. Note when using gzip:

 

http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4691425

 

Problem Description:

 

When using GZIPInputStream to read the gizp file, use the read method, which returns - 1, indicating that the file reading is really over, but this is not the case.

 

 

After these files are decompressed with win RAR in Windows XP or zcat aaa.gz command on linux, all the contents of the files can be obtained. But it's not good to use GZIPInputStream.

 

This bug is that when java reads the gzip file, it has not finished reading, and returns - 1 prematurely, resulting in some files not finished reading.

 

Fortunately, someone has already solved this problem. Here are the solutions:

package x.y.z;



import java.io.InputStream;

import java.io.PushbackInputStream;

import java.io.IOException;



public

class MultiMemberGZIPInputStream extends GZIPInputStream {



    public MultiMemberGZIPInputStream(InputStream in, int size) throws IOException

    {

        // Wrap the stream in a PushbackInputStream...

        super(new PushbackInputStream(in, size), size);

        this.size=size;

    }



    public MultiMemberGZIPInputStream(InputStream in) throws IOException

    {

        // Wrap the stream in a PushbackInputStream...

        super(new PushbackInputStream(in, 1024));

        this.size=-1;

    }



    private MultiMemberGZIPInputStream(MultiMemberGZIPInputStream parent) throws IOException

    {

        super(parent.in);

        this.size=-1;

        this.parent=parent.parent==null ? parent : parent.parent;

        this.parent.child=this;

    }



    private MultiMemberGZIPInputStream(MultiMemberGZIPInputStream parent, int size) throws IOException

    {

        super(parent.in, size);

        this.size=size;

        this.parent=parent.parent==null ? parent : parent.parent;

        this.parent.child=this;

    }



    private MultiMemberGZIPInputStream parent;

    private MultiMemberGZIPInputStream child;

    private int size;

    private boolean eos;



    public int read(byte[] inputBuffer, int inputBufferOffset, int inputBufferLen) throws IOException {



        if (eos) { return -1;}

        if (this.child!=null)

            return this.child.read(inputBuffer, inputBufferOffset, inputBufferLen);



        int charsRead=super.read(inputBuffer, inputBufferOffset, inputBufferLen);

        if (charsRead==-1)

        {

            // Push any remaining buffered data back onto the stream

            // If the stream is then not empty, use it to construct

            // a new instance of this class and delegate this and any

            // future calls to it...

            int n = inf.getRemaining() – 8;

            if (n > 0)

            {

                // More than 8 bytes remaining in deflater

                // First 8 are gzip trailer. Add the rest to

                // any un-read data...

                ((PushbackInputStream)this.in).unread(buf, len-n, n);

            }

            else

            {

                // Nothing in the buffer. We need to know whether or not

                // there is unread data available in the underlying stream

                // since the base class will not handle an empty file.

                // Read a byte to see if there is data and if so,

                // push it back onto the stream...

                byte[] b=new byte[1];

                int ret=in.read(b,0,1);

                if (ret==-1)

                {

                    eos=true;

                    return -1;

                }

                else

                    ((PushbackInputStream)this.in).unread(b, 0, 1);

            }



            MultiMemberGZIPInputStream child;

            if (this.size==-1)

                child=new MultiMemberGZIPInputStream(this);

            else

                child=new MultiMemberGZIPInputStream(this, this.size);

            return child.read(inputBuffer, inputBufferOffset, inputBufferLen);

        }

        else

            return charsRead;

    }



}

Class GZIPInputStream is overridden. Then you can directly introduce the class of MultiMemberGZIPInputStream and call it.

For example:

BufferedReader     bufferedReader = new BufferedReader(new InputStreamReader(new MultiMemberGZIPInputStream(new FileInputStream(gzFile)),

 

http://blog.csdn.net/hwq1987/article/details/6279130

When decompressing gz files, if you directly use java.util.zip.GZIPInputStream to deal with the problem, you can decompress only a small part of the content. You can decompress a gz file completely by using the class multimembergzipiputstream.
 

import java.io.IOException;

import java.io.InputStream;

import java.io.PushbackInputStream;

import java.util.zip.GZIPInputStream;



public class MultiMemberGZIPInputStream extends GZIPInputStream {



public MultiMemberGZIPInputStream(InputStream in, int size)

    throws IOException {

   // Wrap the stream in a PushbackInputStream...

   super(new PushbackInputStream(in, size), size);

   this.size = size;

}



public MultiMemberGZIPInputStream(InputStream in) throws IOException {

   // Wrap the stream in a PushbackInputStream...

   super(new PushbackInputStream(in, 1024));

   this.size = -1;

}



private MultiMemberGZIPInputStream(MultiMemberGZIPInputStream parent)

    throws IOException {

   super(parent.in);

   this.size = -1;

   this.parent = parent.parent == null ? parent : parent.parent;

   this.parent.child = this;

}



private MultiMemberGZIPInputStream(MultiMemberGZIPInputStream parent,

    int size) throws IOException {

   super(parent.in, size);

   this.size = size;

   this.parent = parent.parent == null ? parent : parent.parent;

   this.parent.child = this;

}



private MultiMemberGZIPInputStream parent;



private MultiMemberGZIPInputStream child;



private int size;



private boolean eos;



public int read(byte[] inputBuffer, int inputBufferOffset,

    int inputBufferLen) throws IOException {



   if (eos) {

    return -1;

   }

   if (this.child != null)

    return this.child.read(inputBuffer, inputBufferOffset,

      inputBufferLen);



   int charsRead = super.read(inputBuffer, inputBufferOffset,

     inputBufferLen);

   if (charsRead == -1) {

    // Push any remaining buffered data back onto the stream

    // If the stream is then not empty, use it to construct

    // a new instance of this class and delegate this and any

    // future calls to it...

    int n = inf.getRemaining() - 8;

    if (n > 0) {

     // More than 8 bytes remaining in deflater

     // First 8 are gzip trailer. Add the rest to

     // any un-read data...

     ((PushbackInputStream) this.in).unread(buf, len - n, n);

    } else {

     // Nothing in the buffer. We need to know whether or not

     // there is unread data available in the underlying stream

     // since the base class will not handle an empty file.

     // Read a byte to see if there is data and if so,

     // push it back onto the stream...

     byte[] b = new byte[1];

     int ret = in.read(b, 0, 1);

     if (ret == -1) {

      eos = true;

      return -1;

     } else

      ((PushbackInputStream) this.in).unread(b, 0, 1);

    }



    MultiMemberGZIPInputStream child;

    if (this.size == -1)

     child = new MultiMemberGZIPInputStream(this);

    else

     child = new MultiMemberGZIPInputStream(this, this.size);

    return child.read(inputBuffer, inputBufferOffset, inputBufferLen);

   } else

    return charsRead;

}



}

 

Application example:

try {

    int nnumber;



    FileInputStream fin = new FileInputStream(gzPath);



    MultiMemberGZIPInputStream MmGz = new MultiMemberGZIPInputStream(fin);

    FileOutputStream fout = new FileOutputStream(topath);



    byte[] buf = new byte[1024];



    nnumber = MmGz.read(buf, 0, buf.length);



    while (nnumber != -1) {



         fout.write(buf, 0, nnumber);

         nnumber = MmGz.read(buf, 0, buf.length);



}

    MmGz.close();

    fout.close();

    fin.close();



   } catch (Exception e) {

    e.printStackTrace();

   }

 

79 original articles published, 26 praised, 780000 visitors+
His message board follow

Posted by roomyz on Thu, 13 Feb 2020 06:58:13 -0800