JAVA没有出现gzip格式错误

时间:2015-01-23 06:49:47

标签: java gzip gzipinputstream

我有一个输入流,我试图处理它,但它给了我这个错误“不是gzip格式”但文件是gzip格式“Content-Encoding:gzip”

protected String readResponse(InputStream is) throws IOException {
StringBuffer string;
int b;
byte[] buffer;
String eol, s = null;
GZIPInputStream gis;
int read;
int index;


eol = new String(new byte[] {(byte)0, (byte)0, (byte)-1, (byte)-1});
buffer = new byte[1];
string = new StringBuffer();
while ( (b = is.read()) > 0 ) {
  buffer[0] = (byte)b;
  s = new String(buffer);
  string.append(s);
  index = string.indexOf(eol);
  if ( index > 0 && index == string.length() - 4 ) {
    break;
  }

}

System.out.println(string);

gis = new GZIPInputStream(is); << here I got the error
buffer = new byte[1024]; 

while ( (read = gis.read(buffer)) > 0 ) {
  string.append(new String(buffer, 0, read));
}
return string.toString();

}

任何想法? 感谢

4 个答案:

答案 0 :(得分:1)

看到这一行:

  

eol = new String(new byte [] {(byte)0,(byte)0,(byte)-1,(byte)-1});

足以得出结论:你从一开始就注定要失败。

不要使用字符串数据

bytechar s彼此没有任何关系;你在这里做的大致相当于以下几点:

final CharsetDecoder decoder = Charset.defaultCharset()
    .newDecoder().onMalformedInput(CodingErrorAction.REPLACE);
final ByteBuffer buf = ByteBuffer.wrap(new byte[]{...});
final CharBuffer cbuf = decoder.decode(buf);
final String eol = new String(cbuf.array());

请注意REPLACE操作。任何不可映射的字节序列都会触发解码器输出Unicode替换字符U+FFFD(看起来很熟悉,对吧?)。

现在尝试改为REPORT

更重要的是,您使用默认字符集...这在平台之间有所不同。

您的代码应该只是读取输入流并返回byte数组。使用ByteArrayOutputStream

如果你想直接写一个文件,那很简单:使用Files.copy()

无论如何,为你解决了这个问题:

// Note: return code is byte[]
protected byte[] readResponse(final InputStream in)
    throws IOException
{
    try (
        final InputStream gzin = new GzipInputSream(in);
        final ByteArrayOutputStream out = new ByteArrayOutputStream();
    ) {
        final byte[] buf = new byte[4096];
        int bytesRead;
        while ((bytesRead = gzin.read(buf)) != -1)
            out.write(buf, 0, bytesRead);

        return out.toByteArray();
    }
}

答案 1 :(得分:0)

问题可能是你在将输入流传递给GZIPInputStream之前推进了输入流中的文件指针。 GZIPInputStream期望前几个字节是标准头。

尝试移动新的GZIPInputStream(是);在你的while循环之前

答案 2 :(得分:0)

您的代码中存在许多错误.....但无论如何都要尝试。 所以你有ascii标题,然后有zzipped部分吗? Gzip文件始终以id字节开头。它们具有固定值&#39; ID1 = 31(0x1f,\ 037),ID2 = 139(0x8b,\ 213)&#39;。你能从输入流中找到那些。那里你应该启动gzipstream。

答案 3 :(得分:0)

我用一个由几个标题行组成的文件,后面跟一个空行和一个附加的gzip压缩文本文件来测试它。后者写成,未展开,到x.gz并解压缩并从那里读取,假设它是一个文本文件。 (如果它是二进制文件,则BufferedReader是没有意义的。)

尝试/使用资源和捕获应该添加,但这只是一个技术性。

InputStream is = ...;
StringBuilder lsb = new StringBuilder();
int c = -1;
while( (c = is.read()) != -1 ){
    if( c == '\n' ){
        String line = lsb.toString();
        if( line.matches( "\\s*" ) ){
            break;
        }
        System.out.println( line );
        lsb.delete( 0, lsb.length() );
    } else {
        lsb.append( (char)c );
    }
}
byte[] buffer = new byte[1024];
int nRead = 0;
OutputStream os = new FileOutputStream( "x.gz" );
while ( (nRead = is.read(buffer, 0, buffer.length )) > 0 ) {
    os.write( buffer, 0, nRead );
}
os.close();
is.close();

InputStream gis = new GZIPInputStream( new FileInputStream( "x.gz" ) );
InputStreamReader isr = new InputStreamReader( gis );
BufferedReader br = new BufferedReader(isr);
String line;
while( (line = br.readLine()) != null ){
    System.out.println("line: " + line );
}
br.close();