GZIPInputStreampublic 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. |
Fields Summary |
---|
protected CRC32 | crcThe checksum algorithm used when handling uncompressed data. | protected boolean | eosIndicates the end of the input stream. | public static final int | GZIP_MAGICThe 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.
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}.
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 void | close()
eos = true;
super.close();
| private long | getLong(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 int | getShort(byte[] buffer, int off)
return (buffer[off] & 0xFF) | ((buffer[off + 1] & 0xFF) << 8);
| public int | read(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 void | readFully(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 void | readZeroTerminated(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);
}
|
|