2025-05-23

關於GZIPInputStream的bug,在jdk的最新版本上竟然還沒解決這個問題。用到gzip的需要註意瞭: 
 
http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4691425 
 
問題描述: 
 
在使用GZIPInputStream對gizp文件進行讀取的時候,使用read方法,方法返回-1,表示該文件讀取真正的結束,但是實際卻並不是這樣。 
 
 
這些文件在windowsxp用win-rar解壓或者linux上zcat aaa.gz命令進行解壓後,是可以獲得文件的全部內容的。但是在使用GZIPInputStream卻不行。 
 
這個bug是java在讀取gzip文件的時候,還沒有讀取完畢,過早的返回-1,造成有部分文件沒有讀取完畢。 
 
不過好在已經有人解決這個問題瞭,下面是解決的方法: 
 
 
 
Java代碼  收藏代碼 
 
    package x.y.z;   
       
    import java.io.InputStream;   
    import java.io.PushbackInputStream;   
    import java.io.IOException;   
       
    public   
    class MultiMemberGZIPInputStream extends GZIPInputStream {   
       
        public MultiMemberGZIPInputStream(InputStream in, int size) throws IOException   
        {   
            // Wrap the stream in a PushbackInputStream…   
            super(new PushbackInputStream(in, size), size);   
            this.size=size;   
        }   
       
        public MultiMemberGZIPInputStream(InputStream in) throws IOException   
        {   
            // Wrap the stream in a PushbackInputStream…   
            super(new PushbackInputStream(in, 1024));   
            this.size=-1;   
        }   
       
        private MultiMemberGZIPInputStream(MultiMemberGZIPInputStream parent) throws IOException   
        {   
            super(parent.in);   
            this.size=-1;   
            this.parent=parent.parent==null ? parent : parent.parent;   
            thisthis.parent.child=this;   
        }   
       
        private MultiMemberGZIPInputStream(MultiMemberGZIPInputStream parent, int size) throws IOException   
        {   
            super(parent.in, size);   
            this.size=size;   
            this.parent=parent.parent==null ? parent : parent.parent;   
            thisthis.parent.child=this;   
        }   
       
        private MultiMemberGZIPInputStream parent;   
        private MultiMemberGZIPInputStream child;   
        private int size;   
        private boolean eos;   
       
        public int read(byte[] inputBuffer, int inputBufferOffset, int inputBufferLen) throws IOException {   
       
            if (eos) { return -1;}   
            if (this.child!=null)   
                return this.child.read(inputBuffer, inputBufferOffset, inputBufferLen);   
       
            int charsRead=super.read(inputBuffer, inputBufferOffset, inputBufferLen);   
            if (charsRead==-1)   
            {   
                // Push any remaining buffered data back onto the stream   
                // If the stream is then not empty, use it to construct   
                // a new instance of this class and delegate this and any   
                // future calls to it…   
                int n = inf.getRemaining() – 8;   
                if (n > 0)   
                {   
                    // More than 8 bytes remaining in deflater   
                    // First 8 are gzip trailer. Add the rest to   
                    // any un-read data…   
                    ((PushbackInputStream)this.in).unread(buf, len-n, n);   
                }   
                else   
                {   
                    // Nothing in the buffer. We need to know whether or not   
                    // there is unread data available in the underlying stream   
                    // since the base class will not handle an empty file.   
                    // Read a byte to see if there is data and if so,   
                    // push it back onto the stream…   
                    byte[] b=new byte[1];   
                    int ret=in.read(b,0,1);   
                    if (ret==-1)   
                    {   
                        eos=true;   
                        return -1;   
                    }   
                    else   
                        ((PushbackInputStream)this.in).unread(b, 0, 1);   
                }   
       
                MultiMemberGZIPInputStream child;   
                if (this.size==-1)   
                    child=new MultiMemberGZIPInputStream(this);   
                else   
                    child=new MultiMemberGZIPInputStream(this, this.size);   
                return child.read(inputBuffer, inputBufferOffset, inputBufferLen);   
            }   
            else   
                return charsRead;   
        }   
       
    }   
       
    重寫瞭GZIPInputStream這個類。然後你在使用的時候直接引入MultiMemberGZIPInputStream這個類,並調用即可。   
       
    例如:   
       
      BufferedReader     bufferedReader = new BufferedReader(new InputStreamReader(new MultiMemberGZIPInputStream(new FileInputStream(gzFile)),   
關於GZIPInputStream的bug,在jdk的最新版本上竟然還沒解決這個問題。用到gzip的需要註意瞭:

http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4691425

問題描述:

在使用GZIPInputStream對gizp文件進行讀取的時候,使用read方法,方法返回-1,表示該文件讀取真正的結束,但是實際卻並不是這樣。

這些文件在windowsxp用win-rar解壓或者linux上zcat aaa.gz命令進行解壓後,是可以獲得文件的全部內容的。但是在使用GZIPInputStream卻不行。

這個bug是java在讀取gzip文件的時候,還沒有讀取完畢,過早的返回-1,造成有部分文件沒有讀取完畢。

不過好在已經有人解決這個問題瞭,下面是解決的方法:

 

Java代碼  收藏代碼

    package x.y.z; 
     
    import java.io.InputStream; 
    import java.io.PushbackInputStream; 
    import java.io.IOException; 
     
    public 
    class MultiMemberGZIPInputStream extends GZIPInputStream { 
     
        public MultiMemberGZIPInputStream(InputStream in, int size) throws IOException 
        { 
            // Wrap the stream in a PushbackInputStream… 
            super(new PushbackInputStream(in, size), size); 
            this.size=size; 
        } 
     
        public MultiMemberGZIPInputStream(InputStream in) throws IOException 
        { 
            // Wrap the stream in a PushbackInputStream… 
            super(new PushbackInputStream(in, 1024)); 
            this.size=-1; 
        } 
     
        private MultiMemberGZIPInputStream(MultiMemberGZIPInputStream parent) throws IOException 
        { 
            super(parent.in); 
            this.size=-1; 
            this.parent=parent.parent==null ? parent : parent.parent; 
            this.parent.child=this; 
        } 
     
        private MultiMemberGZIPInputStream(MultiMemberGZIPInputStream parent, int size) throws IOException 
        { 
            super(parent.in, size); 
            this.size=size; 
            this.parent=parent.parent==null ? parent : parent.parent; 
            this.parent.child=this; 
        } 
     
        private MultiMemberGZIPInputStream parent; 
        private MultiMemberGZIPInputStream child; 
        private int size; 
        private boolean eos; 
     
        public int read(byte[] inputBuffer, int inputBufferOffset, int inputBufferLen) throws IOException { 
     
            if (eos) { return -1;} 
            if (this.child!=null) 
                return this.child.read(inputBuffer, inputBufferOffset, inputBufferLen); 
     
            int charsRead=super.read(inputBuffer, inputBufferOffset, inputBufferLen); 
            if (charsRead==-1) 
            { 
                // Push any remaining buffered data back onto the stream 
                // If the stream is then not empty, use it to construct 
                // a new instance of this class and delegate this and any 
                // future calls to it… 
                int n = inf.getRemaining() – 8; 
                if (n > 0) 
                { 
                    // More than 8 bytes remaining in deflater 
                    // First 8 are gzip trailer. Add the rest to 
                    // any un-read data… 
                    ((PushbackInputStream)this.in).unread(buf, len-n, n); 
                } 
                else 
                { 
                    // Nothing in the buffer. We need to know whether or not 
                    // there is unread data available in the underlying stream 
                    // since the base class will not handle an empty file. 
                    // Read a byte to see if there is data and if so, 
                    // push it back onto the stream… 
                    byte[] b=new byte[1]; 
                    int ret=in.read(b,0,1); 
                    if (ret==-1) 
                    { 
                        eos=true; 
                        return -1; 
                    } 
                    else 
                        ((PushbackInputStream)this.in).unread(b, 0, 1); 
                } 
     
                MultiMemberGZIPInputStream child; 
                if (this.size==-1) 
                    child=new MultiMemberGZIPInputStream(this); 
                else 
                    child=new MultiMemberGZIPInputStream(this, this.size); 
                return child.read(inputBuffer, inputBufferOffset, inputBufferLen); 
            } 
            else 
                return charsRead; 
        } 
     
    } 
     
    重寫瞭GZIPInputStream這個類。然後你在使用的時候直接引入MultiMemberGZIPInputStream這個類,並調用即可。 
     
    例如: 
     
      BufferedReader     bufferedReader = new BufferedReader(new InputStreamReader(new MultiMemberGZIPInputStream(new FileInputStream(gzFile)),  [html] view plaincopyprint?——————————————————————————-    
   ByteArrayOutputStream arrayOutputStream =new ByteArrayOutputStream();    
   GZIPOutputStream gop = new GZIPOutputStream(arrayOutputStream);      
   byte[] buffer = new byte[1024];      
   int len = 0;    
    while ((len = inputStream.read(buffer)) != -1) {      
    gop.write(buffer, 0, len);    
     }      
       gop.finish(); //這個在寫入arrayOutputStream時一定要有,否則不能完全寫入     
       gop.close;   
 ————————————————————————-   
  Header encoding = method.getResponseHeader("Content-Encoding");            
   if (encoding != null) {                 
  if (encoding.getValue().equals("gzip")) {          
             bytes = GZipUtil.unzip(bytes);           
        }              }                
   public static byte[] unzip(InputStream in) throws IOException {  
             // Open the compressed stream          
     GZIPInputStream gin = new GZIPInputStream(in);        
             ByteArrayOutputStream out = new ByteArrayOutputStream();  
                   // Transfer bytes from the compressed stream to the output stream      
         byte[] buf = new byte[size];            
   int len;             
  while ((len = gin.read(buf)) > 0) {   
                out.write(buf, 0, len);        
       }                    
 // Close the file and stream         
      gin.close();         
      out.close();              
 return out.toByteArray();          }   
——————————————————————————-  
   ByteArrayOutputStream arrayOutputStream =new ByteArrayOutputStream();  
   GZIPOutputStream gop = new GZIPOutputStream(arrayOutputStream);    
   byte[] buffer = new byte[1024];    
   int len = 0;  
    while ((len = inputStream.read(buffer)) != -1) {    
    gop.write(buffer, 0, len);  
     }    
       gop.finish(); //這個在寫入arrayOutputStream時一定要有,否則不能完全寫入   
       gop.close; 
 ————————————————————————- 
  Header encoding = method.getResponseHeader("Content-Encoding");          
   if (encoding != null) {               
  if (encoding.getValue().equals("gzip")) {        
             bytes = GZipUtil.unzip(bytes);         
        }              }              
   public static byte[] unzip(InputStream in) throws IOException {
             // Open the compressed stream        
     GZIPInputStream gin = new GZIPInputStream(in);      
             ByteArrayOutputStream out = new ByteArrayOutputStream();
                   // Transfer bytes from the compressed stream to the output stream    
         byte[] buf = new byte[size];          
   int len;           
  while ((len = gin.read(buf)) > 0) { 
                out.write(buf, 0, len);      
       }                  
 // Close the file and stream       
      gin.close();       
      out.close();            
 return out.toByteArray();          } 

摘自  心飛揚

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *