Как правильно реализовать LZ4, Snappy или аналогичные методы сжатия в Java?

Я попытался внедрить Java-версию LZ4 в программу поисковой системы, пытающуюся искать данные в больших текстовых файлах. Я просто сжимал поток вывода и сохранял его в файлы txt или файлы без имен. Однако я понял, что предположительно сжатые файлы не уменьшились в размере, но даже больше, чем исходные файлы.

В конце концов мне пришлось прибегнуть к zip4j, так как он у меня работает.

Интересно, как я могу использовать банки LZ4 или Snappy для правильного сжатия/распаковки?

Кроме того, как я могу использовать такие алгоритмы для сжатия одной папки с множеством файлов внутри?

Спасибо!


person kdenz    schedule 19.05.2014    source источник
comment
Что вы пробовали, что не сработало? Концептуально вы просто оборачиваете FileOutputStream в OutputStream, который обеспечивает сжатие, а затем записываете в этот поток. Если вы пишете текст, вы, вероятно, захотите обернуть его с помощью OutputStreamWriter или PrintWriter. oss.sonatype.org/service/local/repositories/releases/archive/   -  person Brett Okken    schedule 16.06.2014


Ответы (2)


Я столкнулся с похожей проблемой. Я пытался отправить большой файл (~ 709 МБ) по локальной сети кусками по 8192 байта. Я использовал сжатие/распаковку Lz4, чтобы уменьшить пропускную способность сети.

Итак, если вы пытаетесь сделать что-то подобное, вот мое предложение:

Вот фрагмент аналогичного обычного примера, который вы найдете на https://github.com/jpountz/lz4-java

private static int decompressedLength;
private static LZ4Factory factory = LZ4Factory.fastestInstance();
private static LZ4Compressor compressor = factory.fastCompressor();

public static byte[] compress(byte[] src, int srcLen) {
    decompressedLength = srcLen;
    int maxCompressedLength = compressor.maxCompressedLength(decompressedLength);
    byte[] compressed = new byte[maxCompressedLength];
    compressor.compress(src, 0, decompressedLength, compressed, 0, maxCompressedLength);
    return compressed;
}

Теперь, если вы вернете сжатый байтовый массив как есть, есть большая вероятность, что он может иметь длину больше, чем исходные несжатые данные.

Таким образом, вы можете изменить его следующим образом:

private static int decompressedLength;
private static LZ4Factory factory = LZ4Factory.fastestInstance();
private static LZ4Compressor compressor = factory.fastCompressor();

public static byte[] compress(byte[] src, int srcLen) {
    decompressedLength = srcLen;
    int maxCompressedLength = compressor.maxCompressedLength(decompressedLength);
    byte[] compressed = new byte[maxCompressedLength];
    int compressLen = compressor.compress(src, 0, decompressedLength, compressed, 0, maxCompressedLength);
    byte[] finalCompressedArray = Arrays.copyOf(compressed, compressLen);
    return finalCompressedArray;
}

compressLen хранит фактическую длину сжатых данных, а байтовый массив finalCompressedArray (длиной compressLen) хранит фактические сжатые данные. Его длина, как правило, меньше длины сжатого байтового массива и исходного несжатого байтового массива.

Теперь вы можете распаковать массив байтов finalCompressedArray обычным способом, как показано ниже:

private static LZ4FastDecompressor decompressor = factory.fastDecompressor();

public static byte[] decompress(byte[] finalCompressedArray, int decompressedLength) {
    byte[] restored = new byte[decompressedLength];
    restored = decompressor.decompress(finalCompressedArray, decompressedLength);
    return restored;
}
person Ankit    schedule 03.09.2014
comment
Извините за признание так поздно! - person kdenz; 23.09.2015
comment
@ Ankit- Если я не знаю размер массива байтов после распаковки, какая будет длина распаковки? - person ketan; 29.07.2017

Файл .jar — это файл .zip. Формат файла zip не поддерживает LZ4 или Snappy.

person Mark Adler    schedule 20.05.2014
comment
Ой, неправильный вопрос! :P Я просто имел в виду, как я могу использовать LZ4 или Snappy для сжатия больших текстовых файлов - person kdenz; 20.05.2014