У меня проблема с библиотекой java.util.zip, мое требование - сжать некоторые данные на сервере, распаковать и прочитать их на устройстве Android. Я получил некоторые поврежденные данные, поэтому я попробовал упрощенный тест с ПК, и я мог видеть в отладчике, где он вышел из строя, но я не могу понять, почему. Согласно документации, Java VM и Android используют один и тот же алгоритм сжатия, но байты в том виде, в котором они были записаны дефлятором Java, не были должным образом восстановлены инфлятором в Android. Java VM:
~> java -version
openjdk version "10.0.2" 2018-07-17
OpenJDK Runtime Environment (build 10.0.2+13-suse-lp150.7.1-x8664)
OpenJDK 64-Bit Server VM (build 10.0.2+13-suse-lp150.7.1-x8664, mixed mode)
Среда Android эмулятор: Nexus 5X API 29 x86 (процессор x86)]. В комментарии в коде я добавлю некоторые детали. Deflate на JVM:
byte[] pArray = //Input data
//Before compression, size = 20 bytes
//Data: [-67, 77, 12, 20, -65, 85, -106, 39, -64, 34, 88, -68, 63, -56, -114, -39, -65, 76, 28, -81]
try {
Deflater def = new Deflater();
def.setInput(pArray);
def.finish();
int compressedDataLength = def.deflate(pArray);
def.end();
//After compression data size is still 20 bytes
//Data: [120, -100, -85, -104, -61, 35, -78, 63, 116, -102, -6, 1, -91, -120, 61, -10, 39, -6, 110, -18]
FileOutputStream fout = new FileOutputStream(filePath);
fout.write(pArray, 0, compressedDataLength);
fout.flush();
fout.close();
} catch (IOException e) {
log.error("IO Exception writing compressed data. {}", e);
}
Inflate на Android:
private byte[] expandCompressedData(byte[] cData, int expectedSize) {
//Data coming from the files, 20 bytes equal to those written on the PC
//Data: [120, -100, -85, -104, -61, 35, -78, 63, 116, -102, -6, 1, -91, -120, 61, -10, 39, -6, 110, -18]
//expectedSize = 20
byte expData[] = null;
try {
Inflater decompresser = new Inflater();
decompresser.setInput(cData, 0, cData.length);
expData = new byte[expectedSize];
int resultLength = decompresser.inflate(expData);
//First issue here resultLength = 16
if (resultLength <= 0) {
throw new DataExtractionException("Something went wrong extracting file data. Extracted data size: {}" + resultLength);
}
decompresser.end();
} catch (java.util.zip.DataFormatException ex) {
throw new DataExtractionException("DataFormatException extracting file data: {}" + ex);
}
//The data returned is the same as the input, but truncated and padded by zeroes
//Data: [120, -100, -85, -104, -61, 35, -78, 63, 116, -102, -6, 1, -91, -120, 61, -10, 0, 0, 0, 0 ]
return expData;
}
Кто-нибудь имеет представление о том, почему дефлятор не любит и не извлекает эти данные?
_______________________________
Обновление:
После дальнейшего тестирования я понял, что проблема не имеет ничего общего с JVM -> Android. Я не знаю почему, но эта конкретная последовательность байтов не может быть сжата и восстановлена. Для ясности могу добавить, что байты поступают из массива с плавающей точкой, но это не имеет значения, ошибка происходит независимо от преобразования. Может ли это быть ошибкой в реализации BZIP? В моем случае я решил эту проблему, используя формат gzip.