⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gzipinputstream.java

📁 手机邮箱撒的方式方式方式的
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
//#condition MUJMAIL_COMPRESSED_CONNECTION/* * Created on Jun 25, 2007 at 11:12:23 AM. *  * Copyright (c) 2007 Robert Virkus / Enough Software * * This file is part of J2ME Polish. * * J2ME Polish 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. *  * J2ME Polish 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 J2ME Polish; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA *  * Commercial licenses are also available, please * refer to the accompanying LICENSE.txt or visit * http://www.j2mepolish.org for details. */package mujmail.connections.gzip;import java.io.IOException;import java.io.InputStream;/** * <p>Reads and uncompresses GZIP or DEFLATE encoded input streams.</p> * * <p>Copyright Enough Software 2007 - 2008</p> * <pre> * history *        Jun 25, 2007 - Simon creation * </pre> * @author Simon Schmitt, simon.schmitt@enough.de */public class GZipInputStream extends InputStream {	/**	 * This constant triggers the normal deflate compression as described in rfc 1951.	 */	public static final int TYPE_DEFLATE=0;	/**	 * This constant triggers the gzip compression that is the same as deflate with 	 * some extra header information (see rfc 1952).	 */	public static final int TYPE_GZIP=1;		private InputStream inStream;	private boolean inStreamEnded;		private byte status;	private static final byte EXPECTING_HEADER=0;	private static final byte EXPECTING_DATA=1;	private static final byte EXPECTING_CHECK=2;	private static final byte FINISHED=3;		private boolean hash;	/**	 * The data seems to be decompressed sucessfull if vaildData	 *  is true after processing the whole stream. This is determinded	 *  via counting the processed bytes and depending on the	 *  on the parameters given to the constructor also by using	 *  a CRC32 checksum.	 */	private boolean vaildData;		private int crc32;	private int[] crc32Table=new int[256];		private int type;		// Flags	private boolean BFINAL;//indicates last block	private int BTYPE;// type of compression		// Buffer stuff:	private byte[] window=new byte[32 * 1024]; // every decoder has to support windows up to 32k	private int pProcessed=0;				// data pointer = one after the last processed	private long allPocessed=0;				// amount of processed data mod 2^32		byte[] outBuff;			// the plain data will be stored here before being requested	private int buffsize;	int outEnd=0;						// the position AFTER the last byte of data	int lastEnd=0;						// 		"		the point up to the crc32 was computed	int outStart=0;						// the position of the first bit of data		private int B0len;				// length of remaining plain bytes to process		long[] smallCodeBuffer=new long[2];// (1) contains the merged bitcode and (2) contains the count of those bits	static final byte BL=8; 		// Compression stuff	short[] huffmanTree;		short[] distHuffTree;		/**	 * Creates an input stream capable of GZIP and Deflate with a buffer of 1024 bytes.	 * 	 * @param inputStream 	the stream that contains the compressed data.	 * @param compressionType	TYPE_GZIP or TYPE_DEFLATE	 * @param hash 		set true for data checking, set false for speed reading	 * @throws IOException when the header of a GZIP stream cannot be skipped	 * @see #TYPE_DEFLATE	 * @see #TYPE_GZIP	 */	public GZipInputStream(InputStream inputStream, int compressionType, boolean hash) 	throws IOException	{		this(inputStream, 1024, compressionType, hash);	}		/**	 * Creates an input stream capable of GZIP and Deflate.	 * 	 * @param inputStream 	the stream that contains the compressed data.	 * @param size the size of the internally used buffer	 * @param compressionType	TYPE_GZIP or TYPE_DEFLATE	 * @param hash 		set true for data checking, set false for speed reading	 * @throws IOException when the header of a GZIP stream cannot be skipped	 * @see #TYPE_DEFLATE	 * @see #TYPE_GZIP	 */	public GZipInputStream(InputStream inputStream, int size, int compressionType, boolean hash) 	throws IOException 	{		this.inStream=inputStream;				this.inStreamEnded=false;		this.status=GZipInputStream.EXPECTING_HEADER;				this.hash=hash;		this.type=compressionType;				this.smallCodeBuffer=new long[2];		this.huffmanTree=new short[288*4];						this.distHuffTree=new short[32*4];				this.buffsize=size;		this.outBuff=new byte[size+300];				if (this.type==GZipInputStream.TYPE_GZIP){			ZipHelper.skipheader(inputStream);		}				this.crc32=0;	}	    public void close() throws IOException{    	this.inStream.close();    	    	this.smallCodeBuffer=null;		this.huffmanTree=null;		this.distHuffTree=null;    }	    /**     * This function hides the fact that 'this.window' is a ring buffer     * 		so just pass 'start' and 'len' of data in the window as well     *  	as a destination and it will be copied there.     * @param start     * @param len     * @param dest     */    private void copyFromWindow(int start, int len, byte[] dest, int destoff){    	if (start + len < this.window.length) {    		System.arraycopy(this.window, start, dest, 0+destoff, len);    	} else {    		System.arraycopy(this.window, start, dest, 0+destoff, this.window.length - start);    		System.arraycopy(this.window, 0, dest, this.window.length - start + destoff, len - (this.window.length - start) );    		    	}    }    private void copyIntoWindow(int start, int len, byte[] src, int srcOff){    	if(len + start < this.window.length) {			System.arraycopy(src, srcOff, this.window, start, len);		} else {			System.arraycopy(src, srcOff, this.window, start, this.window.length-start);			System.arraycopy(src, srcOff+(this.window.length-start), this.window, 0, len - (this.window.length-start));		}    	    }            /**     * This function fills the internal outputbuffer reading data form the this.inputStream      *		and inflating it.     * Note: Alf inbuil have bud behavior for interactive protolocs ... try to fill output buffer as much as possible to decrease inflate call     *   Chnage needed to stop after e.g line end in do end of block     */    private void inflate() throws IOException{    	int val=0;    	    	int rep;    	int rem;    	    	int cLen;    	int cPos;    	int aPos;    	    	int copyBytes;    	    	byte[] myWindow=this.window;    	byte[] myOutBuff=this.outBuff;    	    	// shift outputbuffer to the beginning    	System.arraycopy(myOutBuff, this.outStart, myOutBuff, 0, this.outEnd-this.outStart);    	this.outEnd-=this.outStart;    	this.outStart=0;    	    	this.lastEnd = this.outEnd;    	        boolean refill = ( this.inStream.available() == 0); /// Flag whether refillSmallBuffer can call read (and so possibli block) if no data avilable        boolean continueDecodingLoop = true;         if (this.B0len==0){    		if (this.smallCodeBuffer[1]<15){    			refillSmallCodeBuffer( false);                        refill = false;    		}    	}    	    	    	// and fill it by parsing the input-stream    	while ( (myOutBuff.length-this.outEnd>300 && (this.smallCodeBuffer[1]>0  || this.B0len>0)) && this.status!=GZipInputStream.FINISHED){                // parse block header    		if (this.status == GZipInputStream.EXPECTING_HEADER){                    // Process header only if datas are available                    if ( continueDecodingLoop == false ) break;                         processHeader();    		}    		// deal with the data    		    		if (this.status==GZipInputStream.EXPECTING_DATA){	    		// just copy data	    		if (this.BTYPE==0){	    				    			if (this.B0len>0){		    			// copy directly	    				copyBytes=(myOutBuff.length-this.outEnd)>this.B0len ? this.B0len : myOutBuff.length-this.outEnd;	    						    			//at most myOutBuff.length-this.outEnd		    				    				copyBytes=this.inStream.read(myOutBuff, this.outEnd, copyBytes);		    			copyIntoWindow(this.pProcessed, copyBytes, myOutBuff, this.outEnd);		    					    			this.outEnd+=copyBytes;		    			this.pProcessed=(this.pProcessed +copyBytes) & 32767;// % (1<<15);		    					    			this.B0len-=copyBytes;	    			}else{		    			if(this.BFINAL){		    				this.status=GZipInputStream.EXPECTING_CHECK;		    			} else {		    				this.status=GZipInputStream.EXPECTING_HEADER;		    			}		    			if (this.smallCodeBuffer[1]<15){		    				continueDecodingLoop = refillSmallCodeBuffer( refill);                                                refill = false;		    			}	    			}	    				    		}// inflate	    		else {	    				    			if (this.smallCodeBuffer[1]<15){	    				refillSmallCodeBuffer( true); // Can block ... we need this data for decoding	    			}		    			    			val=ZipHelper.deHuffNext(this.smallCodeBuffer,this.huffmanTree);	    					    				    		// normal single byte		    		if (val<256){		    					    			//this.window[this.pProcessed]=(byte)val;		    			myWindow[this.pProcessed]=(byte)val;		    			this.pProcessed=(this.pProcessed +1) &  32767;// % (1<<15);		    					    			myOutBuff[this.outEnd]=(byte)val;		    			this.outEnd++;		    					    					    		}// copy: pointer + len 		    		else if (val!=256) {						if (val>285){							//ERROR: data > 285 was decoded. This is invalid data.;							throw new IOException("1");						}								    			// parse the pointer 								    			// cLen		    			// 		read some bits		    			cLen=popSmallBuffer(ZipHelper.LENGTH_CODE[(val-257)<<1]);		    			//		add the offset		    			cLen+=ZipHelper.LENGTH_CODE[((val-257)<<1)+1];		    					    			// cPos		    			//    	resolve the index		    			if (this.smallCodeBuffer[1]<15){		    				refillSmallCodeBuffer( true);		    			}		    			// DISTANCE		    			val=ZipHelper.deHuffNext(this.smallCodeBuffer, this.distHuffTree);		    					    			//	 	resolve the value		    			cPos=popSmallBuffer(ZipHelper.DISTANCE_CODE[val<<1]);								    			cPos+=ZipHelper.DISTANCE_CODE[(val<<1)+1];		    					    					    			// process the pointer (the data does always fit)		    					    			// the absolute starting position for copying data		    			aPos=this.pProcessed - cPos;		    			aPos+=aPos<0 ? myWindow.length:0;		    					    			// how often will the data be copied?		    			rep=cLen/cPos;		    			rem=cLen-cPos*rep;		    					    			for (int j = 0; j < rep; j++) {		    				// cPos < cLen		    				copyFromWindow(aPos, cPos, myOutBuff,this.outEnd);			    			copyIntoWindow(this.pProcessed, cPos, myOutBuff, this.outEnd);		    				this.outEnd+=cPos;		    				this.pProcessed=(this.pProcessed +cPos) &  32767;//% (1<<15);		    			}		    					    			// cPos > cLen OR remainder 		    			copyFromWindow(aPos, rem, myOutBuff,this.outEnd);// from window into buffer, and again into window		    			copyIntoWindow(this.pProcessed, rem, myOutBuff, this.outEnd);		    			this.outEnd+=rem;		    			this.pProcessed=(this.pProcessed +rem) &  32767;// % (1<<15);		    					    					    		}// val=256		    		else {		    			//System.out.println("Block End code=" + huffmanCode[256] + "  pP="+pProcessed + " popC: " + popcount[0]);		    			if(this.BFINAL){		    				this.status=GZipInputStream.EXPECTING_CHECK;		    			} else {		    				this.status=GZipInputStream.EXPECTING_HEADER;		    			}		    		}		    		if (this.smallCodeBuffer[1]<15){		    			continueDecodingLoop = refillSmallCodeBuffer( refill);		    		}		    	}	    	}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -