本稿では、Zip4j を使ってzipファイルを展開/圧縮する方法について、またパスワード付きzipの扱いについて解説します。
- オープンデータ利用のためにzipを展開してデータ取り込みに利用したい
- 定期的にzipファイルを配信するために、ファイルの圧縮を自動化したい
- (おまけ)zipファイルのパスワードを忘れてしまった
Zip4j とは
Zip4jは、Javaでzipファイルの展開や圧縮を行える包括的なライブラリです。Javaの標準ライブラリや他の様々なzip用のライブラリと違い暗号化をサポートしているため、パスワード付きのzipファイルを扱いたい時は数少ない選択肢の1つとなります。複雑な処理はライブラリが行い、実装がよりシンプルになることを目標に開発されています。
セットアップ
Mavenを使用する場合は、pom.xmlに以下の依存性を追加してください。
pom.xml
特にプロジェクト管理ツールを使わない場合は、jarをダウンロードしてプロジェクトに追加してください。公式でも案内されていますが、ダウンロードはMaven Repositoryから行えます。
サンプルデータ
1つ以上のファイルと1つ以上のディレクトリ、そしてzipファイルのやりとりでありがちな文字化けの確認のため日本語名のファイルを含むzipファイルを用意します。
仙台市の国勢調査のページで公開しているデータが条件に合うため、ここではサンプルデータとして使用しています。
仙台市の昼間人口(平成17年国勢調査 従業地・通学地集計結果その1)(ZIP:839KB)
zipファイルに圧縮する
net.lingala.zip4j.ZipFile
のインスタンスを生成し、addFile()
やaddFolder()
で圧縮したいファイルやディレクトリを追加することで1つのzipファイルにまとめることができます。addFile()はファイル単体を、addFolder()はディレクトリ配下の階層を維持したままファイルを追加できます。
以下のサンプルでは、「248」というディレクトリ以下のファイルとディレクトリを圧縮して「248.zip」というzipファイルを作成しています。
Java
ZipFileインスタンスにファイル/フォルダを追加する際には、net.lingala.zip4j.model.ZipParameters
を圧縮時のパラメータとして指定できます。特に指定しない場合は圧縮アルゴリズムは「DEFLATE」、圧縮レベルは「NORMAL」となります。
パラメータを以下に設定すると、無圧縮となります。この場合、圧縮レベルは無視されます。
zipファイルを展開する
ファイルをすべてを展開する
net.lingala.zip4j.ZipFile
のインスタンスを生成し、extractAll()
ですべてのファイルを展開できます。
以下のサンプルでは、「248.zip」というzipファイルから「248」というディレクトリ以下にファイルを展開しています。
Java
ただし、Windowsの標準アーカイバで圧縮した場合はファイル名のエンコーディングがShiftJISとなるため、Windowsで作成したzipファイルを展開する場合は以下のようにエンコーディングを指定しないと日本語のファイル名は文字化けします。
一部のファイルを抽出する
extractFile()
で指定するファイルを抽出することができます。getFileHeaders()
でzipファイル内に含まれるファイルの情報を取得し、ファイル抽出の引数とします。
以下のサンプルではpngファイルのみ抽出しています。
パスワード付きzipを取り扱う
通常の圧縮/展開処理に加え、パラメータを追加することでパスワード付きのzipも簡単に扱うことができます。
圧縮
パラメータ設定時に、setEncryptFiles(true)
を加えてください。ZipFileインスタンスには、setPassword()
でパスワードを設定します。
上のサンプルではZip標準の暗号アルゴリズムとしていますが、より強固としたい場合はAESを使用することもできます。ただし、Windowsの標準アーカイバでは展開できない場合があります。
注意点として、zipファイル自体は暗号化によって保護されますが、内部のファイル名については読み取り可能です。ファイル名も隠したいといった場合は2重にzip化するといった工夫もできます。
展開
圧縮時と同様にZipFileインスタンスにsetPassword()
でパスワードを設定すると、展開時にそのパスワードが使用されます。
必要なパスワードが無かったり間違えていた場合は、ZipException
が発生します。
参考「パスワードがわからないzipファイルは展開できるか」
これはzipファイルにかけられたパスワードを破ることを推奨しているものではありません。脆弱なパスワードは簡単に破られる可能性があることを理解していただきたい考えで記述しております。くれぐれも悪用されること無いようお願いいたします。
Zip4jの機能としてパスワード解析は提供していませんが、フリーウェアのおまけ機能のように総当たりでパスワードを解析することは可能です。
まず、テストデータを作成しましょう。
続いて、作成したデータに対して総当たりを試行してみましょう。
解析を始めるとわかりますが、PC1台だけでも時間をかければパスワードが解析できてしまいます。パスワード長によりますが、これがクラウドのリソースで並列に処理できるとなればさらに短い時間で破られてしまういます。
大事な書類をパスワード付きzipでやりとりすることはまだ少なからずありますが、パスワードの複雑さについて、さらにはzipでのやりとり自体について考えさせられます。