JAVA не в формате gzip ошибка
У меня есть входной поток, и я попытался обработать его, но он дал мне эту ошибку "не в формате 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 ответа
Видя эту строку:
eol = новая строка (новый байт [] {(байт)0, (байт)0, (байт)-1, (байт)-1});
достаточно прийти к выводу: вы обречены с самого начала.
НЕ ИСПОЛЬЗУЙТЕ СТРОКУ ДЛЯ Двоичных данных.
byte
с и char
не имеют отношения друг к другу; то, что вы делаете здесь, примерно эквивалентно следующему:
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();
}
}
Проблема может заключаться в том, что вы перемещаете указатель файла во входном потоке, прежде чем передать его в GZIPInputStream. GZIPInputStream ожидает, что первые несколько байтов будут стандартным заголовком.
Попробуйте переместить новый GZIPInputStream(is); перед вашим временем цикла
В вашем коде так много неправильного... Но давайте все равно попробуем. Таким образом, у вас есть заголовок ascii и после этого там должны быть gzipped части? Gzip файл всегда начинается с байтов идентификатора. Они имеют фиксированные значения "ID1 = 31 (0x1f, \037), ID2 = 139 (0x8b, \213)". Можете ли вы найти те из вашего входного потока. Там вы должны начать gzipstream.
Я проверил это с помощью файла, состоящего из нескольких строк заголовка, за которым следует пустая строка и добавленный текстовый файл в формате gzipped. Последний записывается, не раскрывается, в 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();