CompressedInputStream.java
上传用户:tanyanyong
上传日期:2013-06-23
资源大小:1355k
文件大小:8k
源码类别:
电子政务应用
开发平台:
MultiPlatform
- /*
- Copyright (C) 2002 MySQL AB
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
- package com.mysql.jdbc;
- import java.io.EOFException;
- import java.io.IOException;
- import java.io.InputStream;
- import java.util.zip.DataFormatException;
- import java.util.zip.Inflater;
- /**
- * @author Mark Matthews
- *
- * To change this generated comment edit the template variable "typecomment":
- * Window>Preferences>Java>Templates.
- * To enable and disable the creation of type comments go to
- * Window>Preferences>Java>Code Generation.
- */
- class CompressedInputStream extends InputStream {
- //~ Instance fields --------------------------------------------------------
- /**
- * The ZIP inflater used to un-compress packets
- */
- private Inflater inflater;
- /**
- * The stream we are reading from the server
- */
- private InputStream in;
- /**
- * The packet data after it has been un-compressed
- */
- private byte[] uncompressedPacket;
- /**
- * The position we are reading from
- */
- private int pos = 0;
- //~ Constructors -----------------------------------------------------------
- /**
- * Creates a new CompressedInputStream that reads
- * the given stream from the server.
- *
- * @param streamFromServer
- */
- public CompressedInputStream(InputStream streamFromServer) {
- this.in = streamFromServer;
- this.inflater = new Inflater();
- }
- //~ Methods ----------------------------------------------------------------
- /**
- * @see java.io.InputStream#available()
- */
- public int available() throws IOException {
- if (this.uncompressedPacket == null) {
- return this.in.available();
- }
- return this.uncompressedPacket.length - this.pos + this.in.available();
- }
- /**
- * @see java.io.InputStream#close()
- */
- public void close() throws IOException {
- this.in.close();
- this.uncompressedPacket = null;
- this.inflater = null;
- }
- /**
- * @see java.io.InputStream#read()
- */
- public int read() throws IOException {
- try {
- getNextPacketIfRequired(1);
- } catch (IOException ioEx) {
- return -1;
- }
- return this.uncompressedPacket[this.pos++] & 0xff;
- }
- /**
- * @see java.io.InputStream#read(byte, int, int)
- */
- public int read(byte[] b, int off, int len) throws IOException {
- if (b == null) {
- throw new NullPointerException();
- } else if ((off < 0) || (off > b.length) || (len < 0)
- || ((off + len) > b.length) || ((off + len) < 0)) {
- throw new IndexOutOfBoundsException();
- }
- if (len <= 0) {
- return 0;
- }
- try {
- getNextPacketIfRequired(len);
- } catch (IOException ioEx) {
- return -1;
- }
- System.arraycopy(this.uncompressedPacket, this.pos, b, off, len);
- this.pos += len;
- return len;
- }
- /**
- * @see java.io.InputStream#read(byte)
- */
- public int read(byte[] b) throws IOException {
- return read(b, 0, b.length);
- }
- /**
- * @see java.io.InputStream#skip(long)
- */
- public long skip(long n) throws IOException {
- long count = 0;
- for (long i = 0; i < n; i++) {
- int bytesRead = read();
- if (bytesRead == -1) {
- break;
- }
- count++;
- }
- return count;
- }
- /**
- * Retrieves and un-compressed (if necessary) the next
- * packet from the server.
- *
- * @throws IOException if an I/O error occurs
- */
- private void getNextPacketFromServer() throws IOException {
- byte[] uncompressedBuffer = null;
- int packetLength = this.in.read() + (this.in.read() << 8)
- + (this.in.read() << 16);
- // -1 for all values through above assembly sequence
- if (packetLength == -65793) {
- throw new IOException("Unexpected end of input stream");
- }
- // we don't look at packet sequence in this case
- this.in.read();
- int compressedLength = this.in.read() + (this.in.read() << 8)
- + (this.in.read() << 16);
- if (compressedLength > 0) {
- uncompressedBuffer = new byte[compressedLength];
- byte[] compressedBuffer = new byte[packetLength];
- readFully(compressedBuffer, 0, packetLength);
- try {
- this.inflater.reset();
- } catch (NullPointerException npe) {
- this.inflater = new Inflater();
- }
- this.inflater.setInput(compressedBuffer);
- try {
- this.inflater.inflate(uncompressedBuffer);
- } catch (DataFormatException dfe) {
- throw new IOException(
- "Error while uncompressing packet from server.");
- }
- this.inflater.end();
- } else {
- //
- // Read data, note this this code is reached when using
- // compressed packets that have not been compressed, as well
- //
- uncompressedBuffer = new byte[packetLength + 1];
- readFully(uncompressedBuffer, 0, packetLength);
- }
- if ((this.uncompressedPacket != null)
- && (this.pos < this.uncompressedPacket.length)) {
- int remainingLength = this.uncompressedPacket.length - this.pos;
- byte[] combinedBuffer = new byte[remainingLength
- + uncompressedBuffer.length];
- System.arraycopy(this.uncompressedPacket, this.pos, combinedBuffer, 0,
- remainingLength);
- System.arraycopy(uncompressedBuffer, 0, combinedBuffer,
- remainingLength, uncompressedBuffer.length);
- uncompressedBuffer = combinedBuffer;
- }
- this.uncompressedPacket = uncompressedBuffer;
- this.pos = 0;
- return;
- }
- /**
- * Determines if another packet needs to be read from the server
- * to be able to read numBytes from the stream.
- *
- * @param numBytes the number of bytes to be read
- * @throws IOException if an I/O error occors.
- */
- private void getNextPacketIfRequired(int numBytes)
- throws IOException {
- if ((this.uncompressedPacket == null)
- || ((this.pos + numBytes) > this.uncompressedPacket.length)) {
- getNextPacketFromServer();
- }
- }
- private final int readFully(byte[] b, int off, int len)
- throws IOException {
- if (len < 0) {
- throw new IndexOutOfBoundsException();
- }
- int n = 0;
- while (n < len) {
- int count = this.in.read(b, off + n, len - n);
- if (count < 0) {
- throw new EOFException();
- }
- n += count;
- }
- return n;
- }
- }