ZipArchiveクラスはZIPアーカイブの作成・展開・編集を行うためのクラス。 .NET Frameworkでは、4.5以降でSystem.IO.Compression.dllを参照に追加することでZipArchiveクラスを使用できる。
ZipArchiveクラス
ZipArchiveクラスはインスタンスを作成する際にStreamとZipArchiveModeを指定する。 ZipArchiveクラスでできる操作と動作は指定したZipArchiveModeによって次のように変わる。
ZipArchiveMode | ZipArchiveクラスの動作 |
---|---|
ZipArchiveMode.Read | ZIPアーカイブを読み込む。 コンストラクタで指定したStreamをZIPアーカイブとして読み込み、展開する。 |
ZipArchiveMode.Create | ZIPアーカイブを作成する。 ZIPアーカイブを作成し、アーカイブに追加された各エントリを圧縮した上で、コンストラクタで指定したStreamに書き込む。 |
ZipArchiveMode.Update | ZIPアーカイブを更新する。 ReadとCreateの操作の両方を行う。 StreamからZIPアーカイブを読み込んで展開し、アーカイブの内容を変更したのち、再び圧縮してStreamに書き込む。 |
ZipArchiveクラスのコンストラクタでは、エントリ名(ZIPアーカイブ内のファイル名)で使用するエンコーディングをEncodingで指定することができる。 (§.エントリ名のエンコーディング (entryNameEncoding))
ZIPアーカイブの展開
ZipArchiveクラスを使ったZIPアーカイブの展開は次の順序で行う。
- ZIPアーカイブのStreamを開く
- 開いたStreamとZipArchiveMode.Readを指定してZipArchiveを作成する
- ZipArchive.EntriesプロパティもしくはZipArchive.GetEntryメソッドで展開したいファイルのZipArchiveEntryを取得する
- 取得したZipArchiveEntryのOpenメソッドメソッドを呼び出してエントリのStreamを取得する
- 取得したエントリのStreamから読み込むことで内容が展開される
次の例は、ZIPアーカイブを展開し、フォルダ構造を維持したまますべてのエントリを展開するもの。 なお、ZipFile.ExtractToDirectoryメソッドを使うと、以下の例と同等のコードをメソッド呼び出し1つで実現できる。 また、ファイルへの展開には拡張メソッドExtractToFileを使うこともできる。
ZIPアーカイブの作成
ZipArchiveクラスを使ったZIPアーカイブの作成は次の順序で行う。
- ZIPアーカイブを書き込むためのStreamを開く
- 開いたStreamとZipArchiveMode.Createを指定してZipArchiveを作成する
- ZipArchive.CreateEntryメソッドでZipArchiveEntryを作成する
- 作成したZipArchiveEntryのOpenメソッドメソッドを呼び出してエントリのStreamを取得する
- 取得したエントリのStreamに書き込む事で圧縮して格納される
- 必要に応じてファイル属性・パーミッションを指定する (§.ファイル属性・パーミッションの指定 (ExternalAttributes))
次の例は、フォルダ構造を維持したままフォルダ内のファイルを圧縮してZIPアーカイブを作成するもの。 なお、ZipFile.CreateFromDirectoryメソッドを使うと、以下の例と同等のコードをメソッド呼び出し1つで実現できる。 また、ファイルからZipArchiveEntryを作成するには拡張メソッドCreateEntryFromFileを使うこともできる。
圧縮レベルの指定 (CompressionLevel)
ZipArchive.CreateEntryメソッドでZipArchiveEntryを作成する際、同時に引数で圧縮レベルを指定することができる。 圧縮レベルの指定に使うCompressionLevel列挙体の値には次のようなものがある。
CompressionLevel | 圧縮レベル |
---|---|
CompressionLevel.Optimal | 圧縮率優先 |
CompressionLevel.Fastest | 圧縮速度優先 |
CompressionLevel.NoCompression | 無圧縮 |
ZIPアーカイブの変更・更新
ZipArchiveクラスを使ったZIPアーカイブの変更・更新は次の順序で行う。
- ZIPアーカイブを読み込むためのStreamを開く (このStreamは読み書き可能である必要がある)
- 開いたStreamとZipArchiveMode.Updateを指定してZipArchiveを作成する
- ZIPアーカイブの作成の場合と同様の手順でZipArchiveEntryを作成してファイルを追加する
- もしくはZIPアーカイブの展開の場合と同様の手順でZipArchiveEntryを取得し、Deleteメソッドで不要なエントリを削除する
- 変更した内容はStreamに書き込まれてZIPアーカイブは更新される
次の例は、ZIPアーカイブを開いて、ZIPアーカイブ内に格納されているフォルダを削除するもの。
ファイル属性・パーミッションの指定 (ExternalAttributes)
ZipArchiveEntry.ExternalAttributesプロパティを参照することにより、ファイル属性・パーミッションを設定・取得することができる。 アーカイブする際にファイル属性を保存したい場合、逆に展開時にファイル属性を復元したい場合に、この属性を設定・取得する。 ExternalAttributesプロパティは、.NET Framework 4.7.2以降で使用することができる。
ExternalAttributesプロパティの値は、ZIPファイルフォーマットにおけるexternal file attributesの値としてマッピングされる。 ExternalAttributesプロパティの値のうち、下位16ビットはMS-DOSのディレクトリ属性(ファイル属性、FileAttributes列挙体相当)、上位16ビットはUnixのファイルパーミッションにマッピングされると記載されている。
ZipArchive.CreateEntryメソッド・ZipFileExtensions.CreateEntryFromFileメソッドで作成したZipArchiveEntryでは、ExternalAttributesプロパティの初期値は0
となる(ファイルの属性・パーミッションは自動的に反映・マッピングされない)。 そのため、ExternalAttributesプロパティを特に指定せずに作成したZIPアーカイブをUnix系のファイルシステムで展開すると、パーミッションは000になり、読み取りすらできないファイルとして展開されてしまう。
例えば、§.ZIPアーカイブの作成のコードで作成したファイルを展開すると、パーミッションは次のように000なる。
ExternalAttributesプロパティにUnixファイルパーミッションを指定してZIPアーカイブを作成する場合、次のようにExternalAttributesプロパティの上位16ビットにファイルパーミッションを指定する。
エントリ名のエンコーディング (entryNameEncoding)
ZipArchiveコンストラクタ、あるいはZipFile.Openメソッドの引数entryNameEncoding
を指定することで、ZIPアーカイブ内を展開・作成する際のエントリ名のエンコーディングを指定することができる。 ZipFile.OpenReadメソッドには引数entryNameEncoding
が存在しないため、エンコーディングを指定する必要がある場合は、ZipFile.Openメソッドを使用する。
この値を指定しない場合、エントリ名はUTF-8であるものとしてエンコード/デコードされる。 ZIPアーカイブをUTF-8以外で作成する必要がある場合、UTF-8以外のエンコーディングで作成されたアーカイブを展開する場合などには、entryNameEncoding
に対して目的のEncodingを明示的に指定する必要がある。
ZipArchiveMode.Updateを指定してZIPアーカイブの更新を行う場合、展開と圧縮でどちらも同じentryNameEncoding
が使用されることになる。 そのため、ZIPアーカイブの更新ではエンコーディングの変更を行うことはできない。 エンコーディングの変更を行う場合は、一旦アーカイブを展開したのち、目的のエンコーディングを指定した別のアーカイブとして再圧縮する必要がある。
ZipFileクラス
ZipFileクラスには、ZIPアーカイブを扱う際によく行われる操作に対応するユーティリティメソッドが用意されている。 フォルダをまるごとZIPアーカイブとして圧縮したり、逆にZIPアーカイブをフォルダに展開するといった単純な操作は、ZipFileクラスのメソッドを呼び出すだけで行うことができる。
アセンブリSystem.IO.Compression.dllに含まれるZipArchiveクラスに対して、ZipFileクラスはSystem.IO.Compression.FileSystem.dllに含まれるので、使う場合にはこのアセンブリも参照に含める必要がある。
ZIPアーカイブの展開
ZipFile.ExtractToDirectoryメソッドを使うと、ZIPアーカイブを任意のフォルダに展開できる。
ZIPアーカイブの作成
ZipFile.CreateFromDirectoryメソッドを使うと、指定したフォルダの内容を圧縮してZIPアーカイブを作成できる。
引数includeBaseDirectoryにtrueを指定した場合、アーカイブされるファイルにはディレクトリ名も含まれる(フォルダ構造が維持される)。 falseを指定した場合は、ファイルのみとなる(フラットな構造でアーカイブされる)。 falseを指定した場合、既に同名のファイルがアーカイブ内に存在する場合はIOExceptionがスローされる。
拡張メソッド
System.IO.Compression.FileSystem.dllを参照に追加すると、ZipArchiveクラスおよびZipArchiveEntryクラスに拡張メソッドが追加される。 拡張メソッドを使うことにより、ZIPアーカイブの操作をよりシンプルに記述できる。
ExtractToDirectory
ExtractToDirectoryメソッドはZipArchiveクラスに対して追加される拡張メソッドで、ZipArchiveに含まれるすべてのファイルを指定したフォルダに展開して保存する。 従って、ExtractToDirectoryはZipFile.ExtractToDirectoryと同等の動作を行うメソッドとなる。
ExtractToFile
ExtractToFileメソッドはZipArchiveEntryクラス対して追加される拡張メソッドで、ZipArchiveEntryの内容を展開して指定したファイル名で保存することができる。 このメソッドは展開する際のファイル名を変更したり、個別に指定したりしたい場合などに使うことができる。
CreateEntryFromFile
CreateEntryFromFileメソッドはZipArchiveクラス対して追加される拡張メソッドで、指定したファイルの内容でZipArchiveEntryを作成し、ZipArchiveに追加することができる。