📄 gzipinputstream.java
字号:
if (this.status == GZipInputStream.EXPECTING_CHECK){ //System.out.println(this.allPocessed + " data check"); this.status=GZipInputStream.FINISHED; this.allPocessed=(this.allPocessed+this.outEnd-this.lastEnd) & 4294967295L; if (this.hash){ // lastEnd -> End in CRC32 einbeziehen this.crc32=ZipHelper.crc32(this.crc32Table, this.crc32, myOutBuff, this.lastEnd, this.outEnd-this.lastEnd); } // skip till next byte boundary, read CRC , isize popSmallBuffer(this.smallCodeBuffer[1]&7); int cCrc=popSmallBuffer(8)|(popSmallBuffer(8)<<8)|(popSmallBuffer(8)<<16)|(popSmallBuffer(8)<<24); int iSize=popSmallBuffer(8)|(popSmallBuffer(8)<<8)|(popSmallBuffer(8)<<16)|(popSmallBuffer(8)<<24); this.vaildData=(iSize==this.allPocessed); if (this.hash){ this.vaildData &= (this.crc32==cCrc); } if (!this.vaildData){ //ERROR: the data check (size & hash) are wrong throw new IOException("2"); } } } // refresh the checksum at once if (this.status!=GZipInputStream.FINISHED){ this.allPocessed=(this.allPocessed+this.outEnd-this.lastEnd) & 4294967295L; if (this.hash){ // lastEnd -> End in CRC32 einbeziehen this.crc32 = ZipHelper.crc32(this.crc32Table, this.crc32, myOutBuff, this.lastEnd, this.outEnd-this.lastEnd); } } } private void processHeader () throws IOException{ int val; int HLIT; // number of miniHuff fragments int HDIST;// number of distance codes (should somehow lead to the same) int HCLEN;// number of length codes int[] distHuffCode=new int[30]; int[] distHuffData=new int[30]; byte[] distHuffCodeLength=new byte[30]; int[] huffmanCode=new int[286]; // this contains the codes according to the huffman tree/mapping int[] huffmanData=new int[286]; // this contains the data referring to the code. byte[] huffmanCodeLength=new byte[286]; this.BFINAL= (popSmallBuffer(1)==1); this.BTYPE=popSmallBuffer(2); if (this.BTYPE==3){ throw new IllegalArgumentException(); } else if (this.BTYPE==1){ //System.out.println(this.allPocessed + ": fixed tree"); ZipHelper.genFixedTree(huffmanCode, huffmanCodeLength, distHuffCode, distHuffCodeLength); for (int i = 0; i < 286; i++) { huffmanData[i]=i; } for (int i = 0; i < 30; i++) { distHuffData[i]=i; } // convert literal table to tree ZipHelper.convertTable2Tree(huffmanCode, huffmanCodeLength, huffmanData, this.huffmanTree); // convert distance table to tree ZipHelper.convertTable2Tree(distHuffCode, distHuffCodeLength, distHuffData, this.distHuffTree); } else if(this.BTYPE==2) { //System.out.println(this.allPocessed + ": dynamic tree"); // read/parse the length codes HLIT=popSmallBuffer(5); HDIST=popSmallBuffer(5); HCLEN=popSmallBuffer(4); // miniTree int[] miniHuffData= { 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; int[] seq={0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18}; byte[] miniHuffCodeLength=new byte[19]; int[] miniHuffCode=new int[19]; // read the miniHuffCodeLength for (int i = 0; i < HCLEN+4; i++) { miniHuffCodeLength[ miniHuffData[i] ]=(byte) popSmallBuffer(3); } ZipHelper.genHuffTree(miniHuffCode, miniHuffCodeLength); ZipHelper.revHuffTree(miniHuffCode, miniHuffCodeLength); short[] miniTree = new short[19*4]; ZipHelper.convertTable2Tree(miniHuffCode, miniHuffCodeLength, seq, miniTree); // parse the length code for the normal Tree and the distance Tree using the miniTree for (int i = 0; i < huffmanCodeLength.length; i++) { huffmanCodeLength[i]=0; } for (int i = 0; i < distHuffCodeLength.length; i++) { distHuffCodeLength[i]=0; } byte lastVal=0; for (int j = 0; j < HLIT + 257 + HDIST +1;) { if (this.smallCodeBuffer[1]<15){ refillSmallCodeBuffer( true); } val=ZipHelper.deHuffNext(this.smallCodeBuffer, miniTree); // data if (val<16){ lastVal=(byte)val; val=1; } else{ // repeat code if (val==16){ val=popSmallBuffer(2)+3; } else if (val==17){ lastVal=0; val=popSmallBuffer(3)+3; } else if (val==18){ lastVal=0; val=popSmallBuffer(7)+11; } } // fill the value in for (int k = 0; k < val; k++,j++) { if (j<HLIT + 257){ huffmanCodeLength[j]=lastVal; } else { distHuffCodeLength[j-(HLIT + 257)]=lastVal; } } } // final tree: fill this.huffmanCode this.huffmanData ZipHelper.genHuffTree(huffmanCode, huffmanCodeLength); for (int i = 0; i < huffmanData.length; i++) { huffmanData[i]=i; } // converting literal table to tree ZipHelper.revHuffTree(huffmanCode, huffmanCodeLength); ZipHelper.convertTable2Tree(huffmanCode, huffmanCodeLength, huffmanData, this.huffmanTree); // Distance Tree // distHuffData for non fixed distance tree // this.distHuffCodeLength is read together with this.huffmanCodeLength for (int j = 0; j < distHuffCode.length; j++) { distHuffData[j]=j; } ZipHelper.genHuffTree(distHuffCode, distHuffCodeLength); ZipHelper.revHuffTree(distHuffCode, distHuffCodeLength); ZipHelper.convertTable2Tree(distHuffCode, distHuffCodeLength, distHuffData, this.distHuffTree); } else{ // just skip bits up to the next boundary popSmallBuffer(this.smallCodeBuffer[1]&7); //&7 == %8 // read and check the header this.B0len=popSmallBuffer(8)|popSmallBuffer(8)<<8; if (this.smallCodeBuffer[1]<15){ refillSmallCodeBuffer( true); } if (this.B0len + (popSmallBuffer(8)|popSmallBuffer(8)<<8) != 0xffff){ //Error: the header for the uncompressed is wrong; throw new IOException("3"); } // clear the buffer while(this.smallCodeBuffer[1]!=0 && this.B0len>0){ val = popSmallBuffer(8); this.window[this.pProcessed]=(byte)val; this.pProcessed=(this.pProcessed +1) & 32767; // == % (1<<15); this.outBuff[this.outEnd]=(byte)val; this.outEnd++; this.B0len--; } } this.status=GZipInputStream.EXPECTING_DATA; distHuffCode=null; distHuffData=null; distHuffCodeLength=null; huffmanCodeLength=null; huffmanCode=null; huffmanData=null; } /** * Checks if the current status is valid * * @return -1 if the stream is finished, 1 if the current data is valid, 0 if not * @throws IOException */ public int validData() throws IOException{ inflate(); if (this.status!=GZipInputStream.FINISHED){ return -1; } else { if (this.vaildData){ return 1; } else { return 0; } } } private int popSmallBuffer(long len) throws IOException{ if (len==0) return 0; if (this.smallCodeBuffer[1]<len){ refillSmallCodeBuffer( true); } int ret= (int) (this.smallCodeBuffer[0] & ((1<<len)-1)); this.smallCodeBuffer[0]>>>=len; this.smallCodeBuffer[1]-=len; return ret; } /** * This function refills the smallCodeBuffer with data from the input * stream. * */ byte[] tmpRef = new byte[8]; // just one allocation /** * Refill mini internal buffer used for internal decoding. * Only (nearly) function that reads input. * * @param canBlock If true check if datas are available * @return true if any pending data are in buffer * @throws java.io.IOException */ private boolean refillSmallCodeBuffer( boolean canBlock) throws IOException{ // (re)fill this.smallBuffer reading this.inStream if (this.inStreamEnded==false){ int wanted=(int)(BL-this.smallCodeBuffer[1]/8-1); int count = 0; int avail = 9999; if ( canBlock || ((avail=this.inStream.available()) >= wanted) ) count= this.inStream.read(this.tmpRef,0,wanted); if (count == -1){ this.inStreamEnded=true; } for (int i = 0; i < count; i++) { this.smallCodeBuffer[0]&= ~( (long)0xff << this.smallCodeBuffer[1]); if (this.tmpRef[i]<0){ this.smallCodeBuffer[0]|= (long)(this.tmpRef[i]+256) << this.smallCodeBuffer[1]; }else{ this.smallCodeBuffer[0]|= (long)this.tmpRef[i] << this.smallCodeBuffer[1]; } this.smallCodeBuffer[1]+=8; }// return avail > 8 + count; return avail > 0; } return false; // Stream closed } /** * This function fills the buffer and returns the amount of * avialable data. Therefore it will always return the buffer * size that was given to the constructor. */ public int available() throws IOException {// if ((this.outEnd-this.outStart)<this.outBuff.length-300){// inflate();// } // Alf - inflate only when needed if (this.outEnd==this.outStart){ inflate(); } return this.outEnd-this.outStart; } public long skip(long n) throws IOException{ long skipped=0; byte b[]=new byte[this.buffsize]; while(skipped<n && this.status != GZipInputStream.FINISHED){ skipped+=this.read(b); } return skipped; } public int read() throws IOException { if ((this.outEnd-this.outStart)==0){ inflate(); } if(this.outEnd-this.outStart==0 && this.inStreamEnded){ // the input stream ended return -1; } else { return (this.outBuff[this.outStart++] + 256) & 255; } } public int read(byte b[]) throws IOException { return read(b, 0, b.length); } /* (non-Javadoc) * @see java.io.InputStream#read(byte[], int, int) */ public int read(byte b[], int off, int len) throws IOException { // inflate as much as possible// if ((this.outEnd-this.outStart)<this.outBuff.length-300){// inflate();// } // Alf: Infalte only when needed if (this.outEnd==this.outStart) { inflate(); } // we can process just min(b.length, this.avialableBytes) Bytes int av=this.available(); int copyBytes= len > av ? av: len; // copy avialable data from the ouputBuffer to 'b' // here ocurred an error once System.arraycopy(this.outBuff, this.outStart, b, off, copyBytes); this.outStart+=copyBytes; // return the number of copied bytes if(copyBytes!=0){ return copyBytes; } else { return -1; } } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -