GZIPOutputStream: повышение уровня сжатия

java.util.zip.GZIPOutputStream не предоставляет аргумент конструктора или сеттер для уровня сжатия его базового Deflater.

Есть способы обойти эту проблему, как описано здесь, например:

GZIPOutputStream gzip = new GZIPOutputStream(output) {
    {
        this.def.setLevel(Deflater.BEST_COMPRESSION);
    }
};

I GZIPped 10G файл с этим, и его размер не уменьшался на один бит по сравнению с использованием предустановленного DEFAULT_COMPRESSION.

ответ на этот вопрос говорит, что при определенных обстоятельствах установка уровня может не работать так, как планировалось. Чтобы убедиться, я также попытался создать новый Deflater:

this.def = new Deflater(Deflater.BEST_COMPRESSION, true);

Но не уменьшает размер файла...

Есть ли причина, по которой они не обеспечивали доступ к уровню Deflater?

Или что-то не так с примером кода выше?

Работает ли уровень deflater вообще?

Изменить: спасибо за комментарии.

  • Может ли файл быть сжат дальше?

    Это текстовый файл UTF-8, сжатый с 10G до 10M, используя По умолчанию сжатие. Поэтому, не зная подробностей о уровень сжатия, я полагал, что он может быть сжат дальше.

  • Разница во времени между DEFAULT_COMPRESSION и BEST_COMPRESSION?

    У меня нет времени создавать действительно надежные цифры. Но я выполнил код с каждым уровнем сжатия примерно пять раз и оба заняли примерно одно и то же время (2 минуты +/- 5 секунд).

  • Размер файла с помощью gzip -v9? Файл, созданный gzip, примерно на 15 КБ меньше, чем файл, созданный java. Итак, для моего конкретного случая использования это не стоит больше изучать эту тему.

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

Ответ 1

Да, я немного увеличил коэффициент сжатия данных, используя утилиту java GZIP.

class MyGZIPOutputStream 
    extends GZIPOutputStream {

    public MyGZIPOutputStream( OutputStream out ) throws IOException {
        super( out );
    } 

    public void setLevel( int level ) {
        def.setLevel(level);
    }
}

Просто оберните его вокруг своего потока и установите уровень как

new MyGZIPOutputStream( outputstream ).setLevel( Deflater.BEST_COMPRESSION );

Ниже приведены результаты производительности, которые я попробовал за 3,2 ГБ данных,

Коэффициент сжатия данных до (который использовал сжатие по умолчанию): 1.3823362619139712

Коэффициент сжатия данных после (который использовал наилучшее сжатие): 1.3836412922501984

Я знаю, что это не большое улучшение, но все же прогресс.

Ответ 2

Вы можете скопировать определение GZIPOutputStream, которое представляет собой простой перенос Deflater, и сделать свою собственную версию, изменяя уровень при создании экземпляра Deflater.