JAVA 不是 gzip 格式错误

JAVA not in gzip format error

我有一个输入流,我试图处理它,但它给了我这个错误 "not in gzip format" 但文件是 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();

}

有什么想法吗? 谢谢

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

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

看到这一行:

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

足以得出一个结论:你从一开始就注定了。

不要将字符串用于二进制数据

bytes 和 chars 彼此没有关系;您在这里所做的大致相当于以下内容:

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

此外,您使用默认字符集...因平台而异。

您的代码实际上应该只读取输入流和 return 一个 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();
    }
}

你的代码中有很多错误.....但是我们还是试试吧。 所以你有 ascii header 然后应该有 gzip 部分? Gzip 文件总是以 id 字节开头。它们具有固定值 'ID1 = 31 (0x1f, 7), ID2 = 139 (0x8b, 3)'。你能从你的输入流中找到那些吗?在那里你应该启动 gzipstream。

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

try/with 应该添加资源和捕获,但这只是技术问题。

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