Java Inflater будет зацикливаться иногда - PullRequest
0 голосов
/ 27 марта 2019

В моем приложении я пытаюсь сжать / распаковать байтовый массив, используя класс Inflater / Deflater java.Вот часть кода, который я использовал сначала:

   ByteArrayOutputStream outputStream = new ByteArrayOutputStream(data.length);  
   byte[] buffer = new byte[1024];  
   while (!inflater.finished()) {  
       int count = inflater.inflate(buffer);  
       outputStream.write(buffer, 0, count);  
   }  

Затем, после того, как я развернул код, он случайным образом (очень редко) вызовет зависание всего приложения, и когда я получу дамп потока, я могу определитьчто одна нить висит

    at java.util.zip.Inflater.inflateBytes(Native Method)
    at java.util.zip.Inflater.inflate(Inflater.java:259)
      - locked java.util.zip.ZStreamRef@fc71443
    at java.util.zip.Inflater.inflate(Inflater.java:280)

Это случается не очень часто.Затем я везде погуглил и обнаружил, что это могут быть некоторые пустые байтовые данные, переданные в inflater, и Finished () никогда не вернет true.

Поэтому я использовал обходной путь вместо

while (!inflater.finished()) 

чтобы определить, закончено ли это, я использовал

while (inflater.getRemaining() > 0)

Но это случилось снова.Теперь это заставляет меня задуматься, какова реальная причина, которая вызывает проблему.Не должно быть никакого пустого массива, передаваемого в inflater, даже если он это сделал, почему метод getRemaining () не прерывал цикл while?Кто-нибудь может помочь пожалуйста?Это действительно беспокоит меня.

Ответы [ 2 ]

1 голос
/ 29 апреля 2019

Смущенный той же проблемой, я нахожу эту страницу.

Это мой обходной путь, может помочь:

ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
while (!inflater.finished()) {
    int i = inflater.inflate(buffer);
    if (i == 0) {
        break;
    }
    byteArrayOutputStream.write(buffer, 0, i);
}
0 голосов
/ 29 апреля 2019

Javadoc inflate :

Распаковывает байты в указанный буфер.Возвращает фактическое количество байт без сжатия.Возвращаемое значение 0 указывает, что needsInput () или needsDictionary () должен быть вызван, чтобы определить, требуются ли дополнительные входные данные или предустановленный словарь.В последнем случае, getAdler () может использоваться для получения значения Adler-32 для необходимого словаря.

Так что @Wildo Luo, безусловно, был прав, проверяя возвращаемое значение 0.

byte[] buffer = new byte[1024];  
while (!inflater.finished()) {  
    int count = inflater.inflate(buffer);  
    if (count != 0 ) {
       outputStream.write(buffer, 0, count);  
    } else {
       if (inflater.needsInput()) { // Not everything read
           inflater.setInput(...);
       } else if (inflater.needsDictionary()) { // Dictionary to be loaded
           inflater.setDictionary(...);
       }
    }
}
inflater.end();

Я могу только представить, что в другом месте код не совсем правильный, возможно, по размеру сжатия.Лучше сначала проверь общий код.Существует Inflater(boolean nowrap), требующий дополнительного байта, вызов end().Обработка исключений (попробуйте окончательно).Etcetera.

Для неизвестных данных, неизвестных случаев: с помощью try-catch найдите сжатые данные, чтобы проверить, является ли это ошибкой на основе данных, и для тестирования любого решения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...