0

入力ストリームがあり、それを処理しようとしましたが、「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

4 に答える 4

1

この行を見る:

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代わりに試してみてください。

さらに、デフォルトの文字セットを使用します...これはプラットフォームごとに異なります。

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();
    }
}
于 2015-01-23T07:02:49.143 に答える
0

問題は、GZIPInputStream に渡す前に、入力ストリームでファイル ポインターを進めている可能性があります。GZIPInputStream は、最初の数バイトが標準ヘッダーであることを想定しています。

new GZIPInputStream(is); を移動してみてください。while ループの前に

于 2015-01-23T06:54:40.210 に答える
0

これは、いくつかのヘッダー行とそれに続く空の行、および追加された gzip されたテキスト ファイルから構成されるファイルでテストしました。後者は、展開されていない状態で x.gz に書き込まれ、そこから解凍されて読み取られます (テキスト ファイルであると想定)。(バイナリ ファイルの場合、BufferedReader は無意味です。)

try/with resources と catch を追加する必要がありますが、それは単なる技術的な問題です。

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();
于 2015-01-24T10:50:09.047 に答える
0

コードには非常に多くの間違いがあります.....しかし、とにかく試してみましょう。それで、ASCIIヘッダーがあり、その後gzipされた部分があるはずですか?Gzip ファイルは常に id バイトで始まります。これらは固定値「ID1 = 31 (0x1f, \037)、ID2 = 139 (0x8b, \213)」を持っています。入力ストリームからそれらを見つけることができますか。そこで、gzipstream を開始する必要があります。

于 2015-01-23T17:54:08.343 に答える