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ファイルを作成できるようになります。