koturnの日記

普通の人です.ブログ上のコードはコピペ自由です.

zipファイルの再圧縮ツールを作った

TL;DR

zopfliを用いて,zipファイルを再圧縮し,よりよい圧縮結果を得るCLIツールを作成した.

元ネタはkomiya-atsushi/zipzopであり,これをC# で再実装したものとなるが,

  1. ファイル単位での並列処理が可能
  2. zopfli.dll の関数に渡せるオプションを全て指定可能

という点が異なる.

背景

zopflipngを用いたPNG再圧縮ツールを作成した際に,「多くのzipファイルにもDeflate圧縮が用いられているのだから,zopfliでzipファイルを再圧縮できるはずだ」と考えていた.

探してみると,komiya-atsushi/zipzopというリポジトリが見つかった. しかし,zipファイル内のPNGファイルを並列で再圧縮するツールを作っていた身としては,並列処理できない点を不満に思った.

zopfliのP/Invoke用のライブラリは作成していたので,とりあえずC# で上記のツールを実装することにした.

使用方法

下記の通り. ディレクトリ指定時はそのディレクトリをzipファイルに圧縮した後,再圧縮を行う.

> RecompressZip.exe 【オプション】... 【zipファイル or ディレクトリ】...

オプション

オプション 機能
-b 【数値】, --block-split-max=【数値】 最大のブロック分割数を指定する.0は無制限を意味する.デフォルトは15.
-d, --dry-run 圧縮処理は行うが,ファイル内容の置き換えは行わない.ベンチマーク用のオプション.
-h, --help 使い方を表示し,プログラムを終了する.
-i 【数値】, --num-iteration=【数値】 最大の繰り返し回数を指定する.デフォルトは15.
-r, --replace-force 再圧縮の結果がオリジナルよりも悪かったとしても置き換えを行うようにする.
-v, --verbose zopfli.dllからの標準エラー出力へのデバッグ出力を有効にする.
-V, --verbose-more zopfli.dllからの標準エラー出力へのより詳細なデバッグ出力を有効にする.
--no-block-split ブロック分割を行わないようにする.
--no-overwrite 元のzipファイルの置き換えを行わないようにする.

使用した所感

7zipで作成した最高レベルの圧縮率のzipファイルに対して使用してみたところ,おおよそ1つのファイル(zipファイルエントリ)につき1%弱程度より圧縮することができた. しかし,ファイルによっては7zipの方が結果が良いこともあり,zopfliが万能ということでもなさそうだ.

普段はzipファイルを作成するときには,7zipで作っておいて,数バイトでも小さくしたいならば,本ツールにて再圧縮をかけるとよいと思う(-r を指定しない限り,元のものより悪い結果は採用しない).

または,Excelファイル(.xlsx)のようなアプリケーション自体がさほど圧縮率を気にせずに作成したzipファイルに対して,このツールを用いるとよいと思われる.

制限事項

元ネタをそのまま実装した形なので,下記の通り. これらについては特に対応することを考えていない.

  • 暗号化zip非対応
  • Deflate圧縮以外はそのまま格納(Deflate64も)

参考