System.IO.Packaging 名前空間のクラスを使用して、zip ファイルを作成するプログラムを作ってみました。以下のように第1引数で指定したファイルまたはフォルダを第2引数で指定したファイルにzipファイルとして保存します。
ZipPackageSampe.exe C:\test\archivefolder C:\test\archive.zip
Packaging 名前空間は本来 zip ファイルを作成するためのものではなく、Open Packaging Conventions (OPC)に準拠した複数のデータオブジェクトを格納したデータを作成するためのものだそうです。zipファイルには、[Content_Types].xmlというファイルも作成されます。
1. プログラム
Visual Studio を起動してコンソールアプリケーションプロジェクトを作成します。参照の追加で、WindowsBase.dll を追加します。あとは、既定で作成されるProgram.cs を次のように編集します。
using System; using System.IO; using System.IO.Packaging; using System.Collections.Generic; using System.Linq; using System.Text; namespace ZipPackageSample { /// <summary> /// System.IO.Packaging 名前空間のクラスを使用して zip ファイルを作成するサンプルプログラム /// Open Packaging Conventions (OPC)に準拠した複数のデータオブジェクトを格納したデータを /// 作成するためのクラスであり、本来zipファイルを作成するためのものではないことに注意 /// zipファイルには[Content_Types].xmlというファイルも作成されます。 /// </summary> class Program { /// <summary> /// 第1引数でしたファイルまたはフォルダを、第2引数で指定されたファイル名で /// 圧縮を行う /// </summary> /// <param name="args"></param> static void Main(string[] args) { if (args.Length != 2) { Console.WriteLine("[Usage] ZipPacakgeSample 入力ファイルorフォルダ 出力ファイル"); return; } Compress(args[0], args[1]); } /// <summary> /// ZipPackageを作成する /// </summary> /// <param name="input"></param> /// <param name="output"></param> static void Compress(string input, string output) { DirectoryInfo root; IList<FileSystemInfo> targets = new List<FileSystemInfo>(); if (File.Exists(input)) { FileInfo f = new FileInfo(input); root = f.Directory; targets.Add(f); } else if (Directory.Exists(input)) { DirectoryInfo d = new DirectoryInfo(input); if (d.Equals(d.Root)) throw new Exception("ルートは指定できません"); root = d.Parent; targets.Add(d); } else { throw new Exception("存在しないファイルです"); } Uri rootUri = new Uri(root.FullName); using (Package package = Package.Open(output, FileMode.Create)) { AddPart(package, root, targets); } } private static void AddPart(Package package, DirectoryInfo root, IList<FileSystemInfo> targets) { foreach (FileInfo file in targets.OfType<FileInfo>()) { string relativePath = file.FullName.Substring(root.FullName.Length + 1); Uri relativeUri = new Uri(relativePath, UriKind.Relative); Uri partUri = PackUriHelper.CreatePartUri(relativeUri); PackagePart part = package.CreatePart(partUri, string.Empty); using (FileStream fileStream = new FileStream(file.FullName, FileMode.Open, FileAccess.Read)) { CopyStream(fileStream, part.GetStream()); } } foreach (DirectoryInfo dir in targets.OfType<DirectoryInfo>()) { List<FileSystemInfo> childs = new List<FileSystemInfo>(); childs.AddRange(dir.GetFiles()); childs.AddRange(dir.GetDirectories()); AddPart(package, root, childs); } } // MSDN のサンプルのユーティリティメソッド private static void CopyStream(Stream source, Stream target) { const int bufSize = 0x1000; byte[] buf = new byte[bufSize]; int bytesRead = 0; while ((bytesRead = source.Read(buf, 0, bufSize)) > 0) target.Write(buf, 0, bytesRead); } } }
2. まとめ
今回の説明は以上です。 フリーで公開されているzipライブラリを使用できない場合、アーカイブした圧縮ファイルを作成するには IE に含まれるzipファイルを作成する コンポーネント を使用することが多いのではと思いますが、System.IO.Packaging 名前空間のクラスを使用してzipファイルを作成できるようになります。
さんのコメント: さんのコメント: