Сжатие больших файлов с помощью блоков в Java

Я сжимаю файлы размером более 2 ГБ в Java, используя последовательное применение двух алгоритмов сжатия; один на базе LZ и один на основе Хаффмана. (Это похоже на DEFLATE).

Поскольку 2 ГБ слишком велики для хранения в каком-либо буфере, я должен передать файл через один алгоритм, выводящий временный файл, а затем передать этот временный файл через второй алгоритм, выводящий окончательный файл.

Альтернативой является сжатие файла блоками по 8 МБ (размер, при котором я не получаю сообщение об ошибке нехватки памяти), но тогда я не могу в полной мере воспользоваться преимуществами избыточности во всем файле.

Любые идеи, как выполнить эти операции аккуратнее. Никаких временных файлов и сжатия в блоках? Какие-либо другие инструменты сжатия сжимают блоки? Как они решают эту проблему? С Уважением


person Danny Rancher    schedule 06.02.2014    source источник
comment
Если вы используете 64-битную JVM, вы должны иметь возможность выделить достаточно места в куче для использования НАМНОГО больших блоков (т.е. 1 ГБ вместо 8 МБ). Посмотрите на параметры -Xms и -Xmx JVM.   -  person Jim Garrison    schedule 06.02.2014
comment
Ваши реализации алгоритма не производят никакого вывода, пока они полностью не прочитают ввод? Если это так, вам не повезло, и вам нужно будет использовать временное хранилище. Однако я серьезно сомневаюсь, что это так, каждый алгоритм начинает выдавать результат после того, как прочитает некоторую часть ввода. В этом случае вы можете использовать конвейеры для передачи выходного потока первого алгоритма второму и записи вывода второго на диск.   -  person Jim Garrison    schedule 06.02.2014
comment
Я думаю, вы переоцениваете «способность в полной мере использовать избыточность всего файла». Используйте блоки меньшего размера. Хотя странно, что вы не можете использовать блок размером более 8 МБ. Кажется, у вас очень маленькая куча.   -  person Holger    schedule 06.02.2014


Ответы (3)


Java поставляется с библиотекой “java.util.zip” для сжатия данных в формате ZIP. Общая концепция довольно проста.

Библиотека читает файл с помощью «FileInputStream». И добавьте имя файла в «ZipEntry» и выведите его в «ZipOutputStream».

import java.util.zip.ZipEntry и import java.util.zip.ZipOutputStream используются для импорта папки Zip в программу.

But how can decompress a file

?

person rahul    schedule 07.02.2014
comment
Этот java.util.zip сжимает и объединяет файлы по отдельности, тогда как я хочу использовать парадигму надежного сжатия en. wikipedia.org/wiki/Solid_compression. java.util.zip также не работает с большими файлами (2 ГБ +). - person Danny Rancher; 07.02.2014

Что не так с перенаправлением потоков? Вы можете читать из InputStream, сжимать байты и записывать их в выходной поток, который подключен к входному потоку следующего алгоритма. Взгляните на PipeInputStream и PipeOutputStream.

Я надеюсь, что эти алгоритмы могут работать постепенно.

person AlexR    schedule 06.02.2014
comment
Привет, спасибо за ваш ответ. Я не понимаю, как вы используете слово постепенно. Мой первый алгоритм должен завершиться, прежде чем можно будет применить второй. С Уважением. - person Danny Rancher; 06.02.2014
comment
Я имею в виду, что я надеюсь, что ваш алгоритм может читать ограниченный кусок байтов, сжимать их, записывать их в выходной поток, чтобы перейти к обработке следующего куска, и не нужно держать в памяти весь ввод, чтобы обработать его с начала до тех пор, пока конец. - person AlexR; 06.02.2014
comment
Мой первый алгоритм должен завершиться, прежде чем можно будет применить второй. кажется довольно странным. Работает ли ваш второй алгоритм на выходе первого алгоритма в обратном направлении? - person Mark Adler; 07.02.2014

Вы можете использовать два уровня java.util.zip. Во-первых, просто объедините все файлы (без сжатия). Если возможно, отсортируйте записи по типу файла, чтобы похожие файлы были рядом друг с другом (это повысит степень сжатия). Во-вторых, сжать этот поток. Вам не нужно запускать две отдельные фазы; вместо этого вы можете обернуть первый во второй этап, например CompressStream(ConcatenateFiles(directory)). Таким образом, у вас есть zip-файл внутри другого zip-файла: внешний zip-файл сжат, внутренний нет и содержит все фактические файлы.

Это правда, что у java.util.zip раньше были проблемы с файлами размером более 2 ГБ (я сталкивался с такими проблемами). Однако я считаю, что это имело место только для ZipFile, а не для ZipIn/OutputStream. Кроме того, я думаю, что эти проблемы исправлены в последних версиях Java.

Размер буфера: обычные алгоритмы сжатия, такие как Deflate, не будут работать с размерами блоков больше 64 КБ. Более продвинутые алгоритмы могут выиграть от использования фрагментов большего размера, например bzip2 до 900 КБ, или LZMA2 до 2 МБ. Все остальное, скорее всего, является областью дедупликации данных, которая может иметь или не иметь смысла для чего. ты хочешь сделать.

person Thomas Mueller    schedule 08.02.2014