Ошибка JAVA не в формате gzip

У меня есть входной поток, и я пытался его обработать, но он выдал мне эту ошибку «не в формате gzip», но файл находится в формате gzip «Кодировка содержимого: 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();

}

Есть предположения? Спасибо


person abdulla-alajmi    schedule 23.01.2015    source источник
comment
Так вы говорите, что Java вам лжет?   -  person Kayaman    schedule 23.01.2015
comment
Я не знаю, чего вы пытаетесь достичь с помощью этого кода, но вот подсказка: не используйте String для двоичных данных   -  person fge    schedule 23.01.2015
comment
Можете ли вы опубликовать файл или первые 100 или около того байтов в виде шестнадцатеричного дампа?   -  person Adam    schedule 23.01.2015
comment
Это не полный код - то, как вы его вставили сюда, не может скомпилироваться. Пожалуйста, опубликуйте весь класс!   -  person Nir Alfasi    schedule 23.01.2015
comment
Помимо всего прочего, ваш подход к преобразованию символов предполагает ISO-8859-1 и очень неэффективен. Если вы ищете определенный шаблон byte, я предлагаю вам сделать это, просто просмотрев bytes... а затем преобразовать двоичные данные в текст более традиционными способами. , указав кодировку.   -  person Jon Skeet    schedule 23.01.2015
comment
Почему вы читаете перед применением GZIPInputStream? Начинается ли файл с чего-то перед сжатой частью?   -  person ikettu    schedule 23.01.2015
comment
@Kayaman Я так думаю, лол   -  person abdulla-alajmi    schedule 23.01.2015
comment
Это не HTTP, не так ли?   -  person laune    schedule 23.01.2015
comment
@ikettu Я применил GZIPInputStream до того, как прочитал его, и это не сработало, проверьте код сейчас, System.out.println(string); распечатает информацию заголовка, такую ​​как Content-Encoding: gzip   -  person abdulla-alajmi    schedule 23.01.2015
comment
@laune это розетка   -  person abdulla-alajmi    schedule 23.01.2015
comment
HTTP — это протокол. Скорее всего, вы получите это через сокет. - Заголовок HTTP завершается пустой строкой, поэтому я не понимаю этот разбор 0/0/0xFF/0xFF.   -  person laune    schedule 23.01.2015
comment
@laune, если я запущу свой код, он напечатает это i.imgur.com/6FGodJE.png   -  person abdulla-alajmi    schedule 23.01.2015
comment
Итак, это HTTP-заголовок. Обычная процедура заключается в чтении lines до тех пор, пока не встретится пустая строка (после Content-Type), а затем вы переключитесь на чтение gzip. Или вы читаете с этого момента, пока не встретите конец файла, сохраните байты (память или файл) и прочитаете gzip из этого промежуточного хранилища.   -  person laune    schedule 23.01.2015
comment
@laune именно я читал до тех пор, пока (тип содержимого), затем переключился на gzip, но теперь, после смены сервера, я не мог этого сделать !, и после двух пустых строк есть (f)! я не знаю для чего это   -  person abdulla-alajmi    schedule 24.01.2015
comment
@laune, если я изменил {while ( (b = is.read()) › 0 } на {while ( (b = is.read()) › -1 )}, if покажет мне это i.imgur.com/IbYTe1Y.png   -  person abdulla-alajmi    schedule 24.01.2015
comment
@user2564147 user2564147 Нашел время составить некоторые тестовые данные и закодировать все шаги для чтения заголовка HTTP, за которым следуют данные gzip. Использование промежуточного файла для хранения заархивированных данных кажется наиболее безопасным, но это можно сделать и путем чтения из кеша памяти.   -  person laune    schedule 24.01.2015


Ответы (4)


Увидев эту строку:

eol = новая строка (новый байт [] {(байт) 0, (байт) 0, (байт)-1, (байт)-1});

достаточно, чтобы прийти к выводу: вы обречены с самого начала.

НЕ ИСПОЛЬЗУЙТЕ STRING ДЛЯ ДВОИЧНЫХ ДАННЫХ.

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();
    }
}
person fge    schedule 23.01.2015
comment
код работал, но сервер изменился, после чего он больше не работал! но работал!!! - person abdulla-alajmi; 23.01.2015
comment
Это сработало благодаря везению. Не полагайтесь на удачу. Код, который работает только время от времени, не работает. - person fge; 23.01.2015
comment
все еще получаю ту же ошибку здесь final InputStream gzin = new GZIPInputStream(is); - person abdulla-alajmi; 23.01.2015
comment
Тогда поток действительно не закодирован gzip. Вы только что попробовали и прочитали это просто? - person fge; 23.01.2015
comment
посмотрите на мой код, если я вставлю system.out.println(string); после цикла он напечатает много правильной информации, такой как: идентификатор сеанса и все остальные, а также напечатает эту строку (Content-Encoding: gzip), что означает, что это gzip - person abdulla-alajmi; 23.01.2015
comment
привет fge, как вы думаете, проблема? - person abdulla-alajmi; 24.01.2015
comment
Теперь я бы сказал, что все, что вы можете попробовать, это загрузить контент как необработанный и проанализировать, действительно ли это поток, сжатый gzip .... - person fge; 24.01.2015
comment
Как мне это сделать? см. код laune, я скачал файл .gz, но не смог распаковать его не в формате gzip - person abdulla-alajmi; 24.01.2015
comment
Скачай обычную джейн, затем проанализируй в командной строке. Используйте 1_. - person fge; 24.01.2015

Проблема может заключаться в том, что вы перемещаете указатель файла во входном потоке, прежде чем передать его в GZIPInputStream. GZIPInputStream ожидает, что первые несколько байтов будут стандартным заголовком.

Попробуйте переместить новый GZIPInputStream(is); перед циклом while

person Adam    schedule 23.01.2015

В вашем коде так много ошибок..... Но давайте все же попробуем. Итак, у вас есть заголовок ascii, и после него должна быть сжатая часть? Файл Gzip всегда начинается с байтов идентификатора. Они имеют фиксированные значения «ID1 = 31 (0x1f, \037), ID2 = 139 (0x8b, \213)». Можете ли вы найти их из вашего входного потока. Там вы должны запустить gzipstream.

person ikettu    schedule 23.01.2015
comment
спасибо за помощь, посмотрите на эту картинку i.imgur.com/6FGodJE.png, как можно Я обнаруживаю файл gzip? - person abdulla-alajmi; 23.01.2015
comment
@ikettu Как только вы увидели волшебство, вы уже прошли точку, с которой можно начать читать сжатый gzip-поток. Как ты предлагаешь это приготовить? И почему не проще отслеживать конец HTTP-заголовка? - person laune; 24.01.2015
comment
Можно использовать обратный поток, чтобы заглянуть заранее. Но просто проверка байт-кодов во время тестирования подскажет вам, какие фактические байты обозначают конец заголовков. - person ikettu; 24.01.2015

Я протестировал это с файлом, состоящим из нескольких строк заголовка, за которыми следует пустая строка и добавленный текстовый файл, сжатый 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();
person laune    schedule 24.01.2015
comment
Я нашел файл gzip на своем компьютере и попытался заархивировать его, но он говорит, что не в формате gzip, сервер сказал, что это файл gzip, но это не так! - person abdulla-alajmi; 24.01.2015
comment
Если вы использовали код, который я разместил, я не понимаю, как это могло потерпеть неудачу. - Во всяком случае, у вас есть точная копия того, что было отправлено после пустой строки, завершающей заголовок - возможно, анализ этих байтов может сказать вам, что это на самом деле. Конечно, я не могу получить доступ к реальному сайту... Не уверен, что вы можете перетащить этот сомнительный файл, который у вас есть. -- Я использовал gzip, чтобы создать приложение к файлу, начинающееся с заголовков, и мой фрагмент кода работает с этим нормально. -- По крайней мере: файлы заголовков должны заканчиваться пустой строкой, не показывая никакой тарабарщины после этой строки - так ли это? - person laune; 24.01.2015