FileDocCategorySizeDatePackage
GZIPInputStream.javaAPI DocAndroid 1.5 API7227Wed May 06 22:41:02 BST 2009java.util.zip

GZIPInputStream

public class GZIPInputStream extends InflaterInputStream
The {@code GZIPInputStream} class is used to read data stored in the GZIP format, reading and decompressing GZIP data from the underlying stream into its buffer.
since
Android 1.0

Fields Summary
protected CRC32
crc
The checksum algorithm used when handling uncompressed data.
protected boolean
eos
Indicates the end of the input stream.
public static final int
GZIP_MAGIC
The magic header for the GZIP format.
private static final int
FHCRC
private static final int
FEXTRA
private static final int
FNAME
private static final int
FCOMMENT
Constructors Summary
public GZIPInputStream(InputStream is)
Construct a {@code GZIPInputStream} to read from GZIP data from the underlying stream.

param
is the {@code InputStream} to read data from.
throws
IOException if an {@code IOException} occurs.
since
Android 1.0


                                                                 
         
        this(is, BUF_SIZE);
    
public GZIPInputStream(InputStream is, int size)
Construct a {@code GZIPInputStream} to read from GZIP data from the underlying stream. Set the internal buffer size to {@code size}.

param
is the {@code InputStream} to read data from.
param
size the internal read buffer size.
throws
IOException if an {@code IOException} occurs.
since
Android 1.0

        super(is, new Inflater(true), size);
        byte[] header = new byte[10];
        readFully(header, 0, header.length);
        if (getShort(header, 0) != GZIP_MAGIC) {
            throw new IOException(Messages.getString("archive.1F")); //$NON-NLS-1$;
        }
        int flags = header[3];
        boolean hcrc = (flags & FHCRC) != 0;
        if (hcrc) {
            crc.update(header, 0, header.length);
        }
        if ((flags & FEXTRA) != 0) {
            readFully(header, 0, 2);
            if (hcrc) {
                crc.update(header, 0, 2);
            }
            int length = getShort(header, 0);
            while (length > 0) {
                int max = length > buf.length ? buf.length : length;
                int result = in.read(buf, 0, max);
                if (result == -1) {
                    throw new EOFException();
                }
                if (hcrc) {
                    crc.update(buf, 0, result);
                }
                length -= result;
            }
        }
        if ((flags & FNAME) != 0) {
            readZeroTerminated(hcrc);
        }
        if ((flags & FCOMMENT) != 0) {
            readZeroTerminated(hcrc);
        }
        if (hcrc) {
            readFully(header, 0, 2);
            int crc16 = getShort(header, 0);
            if ((crc.getValue() & 0xffff) != crc16) {
                throw new IOException(Messages.getString("archive.20")); //$NON-NLS-1$
            }
            crc.reset();
        }
    
Methods Summary
public voidclose()

        eos = true;
        super.close();
    
private longgetLong(byte[] buffer, int off)

        long l = 0;
        l |= (buffer[off] & 0xFF);
        l |= (buffer[off + 1] & 0xFF) << 8;
        l |= (buffer[off + 2] & 0xFF) << 16;
        l |= ((long) (buffer[off + 3] & 0xFF)) << 24;
        return l;
    
private intgetShort(byte[] buffer, int off)

        return (buffer[off] & 0xFF) | ((buffer[off + 1] & 0xFF) << 8);
    
public intread(byte[] buffer, int off, int nbytes)

        if (closed) {
            throw new IOException(Messages.getString("archive.1E")); //$NON-NLS-1$
        }
        if(eof){
            return -1;
        }
        // avoid int overflow, check null buffer
        if (off <= buffer.length && nbytes >= 0 && off >= 0
                && buffer.length - off >= nbytes) {
            int val = super.read(buffer, off, nbytes);
            if (val != -1) {
                crc.update(buffer, off, val);
            } else if (!eos) {
                eos = true;
                // Get non-compressed bytes read by fill
                // BEGIN android-changed
                // copied from newer version of harmony
                int size = inf.getRemaining();
                final int trailerSize = 8; // crc (4 bytes) + total out (4
                                            // bytes)
                byte[] b = new byte[trailerSize];
                int copySize = (size > trailerSize) ? trailerSize : size;

                System.arraycopy(buf, len - size, b, 0, copySize);
                readFully(b, copySize, trailerSize - copySize);                
                // END android-changed
                if (getLong(b, 0) != crc.getValue()) {
                    throw new IOException(Messages.getString("archive.20")); //$NON-NLS-1$
                }
                if ((int) getLong(b, 4) != inf.getTotalOut()) {
                    throw new IOException(Messages.getString("archive.21")); //$NON-NLS-1$
                }
            }
            return val;
        }
        throw new ArrayIndexOutOfBoundsException();
    
private voidreadFully(byte[] buffer, int offset, int length)

        int result;
        while (length > 0) {
            result = in.read(buffer, offset, length);
            if (result == -1) {
                throw new EOFException();
            }
            offset += result;
            length -= result;
        }
    
private voidreadZeroTerminated(boolean hcrc)

        int result;
        while ((result = in.read()) > 0) {
            if (hcrc) {
                crc.update(result);
            }
        }
        if (result == -1) {
            throw new EOFException();
        }
        // Add the zero
        if (hcrc) {
            crc.update(result);
        }