关于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)),

-------------------------------------------------------------------------------

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(); }

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐