C#, .NET, SharpCompress でアーカイブの圧縮・展開

C#

概要

SharpCompress ライブラリを使うと、Zip ファイル以外の形式の圧縮・展開もできます。
・Zip – 圧縮・展開が可能。
・Rar, 7Zip – 展開のみ可能。
・Tar – 展開が可能。複数ファイルをまとめるアーカイブが可能だが、圧縮はできない。
・GZip, BZip2, LZip, XZ – 圧縮・展開が可能。複数ファイルのアーカイブはできないので、単一ファイルを圧縮するか、Tar ファイルにアーカイブしてから圧縮する。

GitHub - adamhathcock/sharpcompress: SharpCompress is a fully managed C# library to deal with many compression types and formats.
SharpCompress is a fully managed C# library to deal with many compression types and formats. - GitHub - adamhathcock/sharpcompress: SharpCompress is a fully man...

作成したプログラムはこちらで公開しています。
https://github.com/matsushima-terunao/test_cs/tree/main/ArchiveTest

SharpCompress ライブラリの導入

こちらを参考に NuGet で Visual Studio プロジェクトに SharpCompress ライブラリを導入してください。

archive, reader, writer オブジェクト作成

圧縮ファイルを扱うためのオブジェクトを作成します。
・圧縮ファイル作成用に新規に archive, writer を作成
・既存ファイルや stream から読み込み用に archive, reader を作成
・既存ファイルや stream から更新用に archive, writer を作成

using SharpCompress.Archives;
using SharpCompress.Archives.Zip;
using SharpCompress.Common;
using SharpCompress.Readers;
using SharpCompress.Writers;
using SharpCompress.Writers.Zip;
using System.Text;

string baseDir = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + "/archivetest/"; // マイドキュメント
string srcDir = baseDir + "test/"; // 圧縮したいファイルのあるフォルダー
string dstFile = baseDir + "test.zip"; // 圧縮ファイル名
string dstFile2 = baseDir + "test.tar.gz"; // 圧縮ファイル名
string dstDir = baseDir + "test2"; // 展開先フォルダー

Console.WriteLine("新規 archive, writer");
using (var archive11 = ZipArchive.Create())
using (var archive12 = ArchiveFactory.Create(ArchiveType.Zip))
using (var stream11 = File.Create(dstFile))
using (var writer11 = new ZipWriter(stream11,
	new(CompressionType.Deflate) { LeaveStreamOpen = true,
		ArchiveEncoding = new() { Default = Encoding.UTF8 } })) // ファイル名の文字化け対応
using (var writer12 = WriterFactory.Open(stream11, ArchiveType.Zip,
	new(CompressionType.Deflate) { LeaveStreamOpen = true,
		ArchiveEncoding = new() { Default = Encoding.UTF8 } })) // ファイル名の文字化け対応
{
	Console.WriteLine(archive11);
	Console.WriteLine(archive12);
	Console.WriteLine(stream11);
	Console.WriteLine(writer11);
	Console.WriteLine(writer12);
}
Console.WriteLine("読み込み archive, reader");
using (var archive21 = ArchiveFactory.Open(dstFile))
using (var stream21 = File.OpenRead(dstFile))
using (var archive22 = ArchiveFactory.Open(stream21))
using (var reader21 = ReaderFactory.Open(stream21))
{
	Console.WriteLine(archive21);
	Console.WriteLine(stream21);
	Console.WriteLine(archive22);
	Console.WriteLine(reader21);
}
Console.WriteLine("更新 archive");
using (var archive31 = (IWritableArchive)ArchiveFactory.Open(dstFile))
{
	Console.WriteLine(archive31);
}

圧縮

圧縮ファイル作成用に新規に archive, writer を作成、ファイルを追加して圧縮します。
アーカイブ形式・圧縮形式を ArchiveType.Tar, CompressionType.GZip にすることで、直接 tar.gz 形式ファイルを作成できます。

フォルダー以下の全ファイルを zip ファイルに圧縮

Console.WriteLine($"フォルダー配下を圧縮 {srcDir} {dstFile}");
using (var archive = ZipArchive.Create())
{
	archive.AddAllFromDirectory(srcDir);
	archive.SaveTo(dstFile,
		new(CompressionType.Deflate) { ArchiveEncoding = new() { Default = Encoding.UTF8 } }); // ファイル名の文字化け対応
}

個別にファイルを tar.gz ファイルに圧縮

Console.WriteLine($"指定ファイルを圧縮 {srcDir} {dstFile2}");
using (var stream = File.Create(dstFile2))
using (var writer = WriterFactory.Open(stream, ArchiveType.Tar,
	new(CompressionType.GZip) { LeaveStreamOpen = true,
		ArchiveEncoding = new() { Default = Encoding.UTF8 } })) // ファイル名の文字化け対応
{
	foreach (var entry in new DirectoryInfo(srcDir).EnumerateFiles("*", SearchOption.AllDirectories))
	{
		writer.Write(Path.GetRelativePath(srcDir, entry.FullName), entry);
	}
}

展開

既存ファイルや stream から読み込み用に archive, reader を作成します。そこからすべてのファイルをディレクトリに展開します。またはエントリーから個別にファイルを展開します。
tar.gz 内のファイルを展開する場合は reader を使用します。

zip ファイル内のすべてのファイルを展開

Console.WriteLine($"全て展開 {dstFile} {dstDir}");
if (Directory.Exists(dstDir))
{
	Directory.Delete(dstDir, true);
}
Directory.CreateDirectory(dstDir);
using (var archive = ArchiveFactory.Open(dstFile))
{
	archive.WriteToDirectory(dstDir,
		new ExtractionOptions() { Overwrite = true, ExtractFullPath = true, PreserveFileTime = true, PreserveAttributes = false });
}

tar.gz ファイル内のファイルを個別に展開

Console.WriteLine($"指定ファイルを展開 {dstFile2} {dstDir}");
if (Directory.Exists(dstDir))
{
	Directory.Delete(dstDir, true);
}
Directory.CreateDirectory(dstDir);
using (var stream = File.OpenRead(dstFile2))
using (var reader = ReaderFactory.Open(stream))
{
	while (reader.MoveToNextEntry())
	{
		if (!reader.Entry.IsDirectory)
		{
			reader.WriteEntryToDirectory(dstDir,
				new ExtractionOptions() { Overwrite = true, ExtractFullPath = true, PreserveFileTime = true, PreserveAttributes = false });
		}
	}
}

一覧

既存ファイルや stream から読み込み用に archive, reader を作成します。そこからファイル一覧を取得します。
tar.gz ファイル内のファイル一覧を取得する場合は reader を使用します。archive では tar ファイルを取得できます。

zip ファイル内のファイル一覧

Console.WriteLine($"一覧 {dstFile}");
using (var archive = ArchiveFactory.Open(dstFile))
{
	foreach (var entry in archive.Entries)
	{
		Console.WriteLine(entry);
	}
}

tar.gz ファイル内のファイル一覧

Console.WriteLine($"一覧 {dstFile2}");
using (var stream = File.OpenRead(dstFile2))
using (var reader = ReaderFactory.Open(stream))
{
	while (reader.MoveToNextEntry())
	{
		Console.WriteLine(reader.Entry);
	}
}

追加

既存ファイルや stream から更新用に archive を作成、ファイルを追加して圧縮します。
tar.gz ファイルの場合、archive から tar ファイルを展開し、ファイルを追加して、再度 gz ファイルに圧縮します。

zip ファイルにファイルを追加

Console.WriteLine($"追加 {dstFile} {dstFile + "add.zip"}");
using (var archive = (IWritableArchive)ArchiveFactory.Open(dstFile))
{
	foreach (var entry in new DirectoryInfo(srcDir).EnumerateFiles("*", SearchOption.AllDirectories))
	{
		archive.AddEntry("newfolder/" + entry.Name, entry);
		break;
	}
	archive.SaveTo(dstFile + "add.zip",
		new(CompressionType.Deflate) { ArchiveEncoding = new() { Default = Encoding.UTF8 } }); // ファイル名の文字化け対応
}

tar.gz ファイルにファイルを追加

Console.WriteLine($"追加 {dstFile2} {dstFile2 + "add.tar.gz"}");
// tar を一時ファイルとして展開
using (var archive = ArchiveFactory.Open(dstFile2))
{
	archive.Entries.First().WriteToFile(dstFile2 + "add.tar.tmp",
		new ExtractionOptions() { Overwrite = true, ExtractFullPath = true, PreserveFileTime = true, PreserveAttributes = false });
}
// tar を開く
using (var archive = (IWritableArchive)ArchiveFactory.Open(dstFile2 + "add.tar.tmp"))
{
	// tar にファイル追加
	foreach (var entry in new DirectoryInfo(srcDir).EnumerateFiles("*", SearchOption.AllDirectories))
	{
		archive.AddEntry("newfolder/" + entry.Name, entry);
		break;
	}
	// tar.gz に圧縮
	archive.SaveTo(dstFile2 + "add.tar.gz",
		new(CompressionType.GZip) { ArchiveEncoding = new() { Default = Encoding.UTF8 } }); // ファイル名の文字化け対応
}
File.Delete(dstFile2 + "add.tar.tmp");

削除

既存ファイルや stream から更新用に archive を作成、エントリーからファイルを削除して圧縮します。
tar.gz ファイルの場合、archive から tar ファイルを展開し、エントリーからファイルを削除して、再度 gz ファイルに圧縮します。

zip ファイルからファイルを削除

Console.WriteLine($"削除 {dstFile} {dstFile + "del.zip"}");
using (var archive = (IWritableArchive)ArchiveFactory.Open(dstFile))
{
	foreach (var entry in archive.Entries)
	{
		archive.RemoveEntry(entry);
		break;
	}
	archive.SaveTo(dstFile + "del.zip",
		new(CompressionType.Deflate) { ArchiveEncoding = new() { Default = Encoding.UTF8 } }); // ファイル名の文字化け対応
}

tar.gz ファイルからファイルを削除

Console.WriteLine($"削除 {dstFile2} {dstFile2 + "del.tar.gz"}");
// tar を一時ファイルとして展開
using (var archive = ArchiveFactory.Open(dstFile2))
{
	archive.Entries.First().WriteToFile(dstFile2 + "del.tar.tmp",
		new ExtractionOptions() { Overwrite = true, ExtractFullPath = true, PreserveFileTime = true, PreserveAttributes = false });
}
// tar を開く
using (var archive = (IWritableArchive)ArchiveFactory.Open(dstFile2 + "del.tar.tmp"))
{
	// tar からファイル削除
	foreach (var entry in archive.Entries)
	{
		archive.RemoveEntry(entry);
		break;
	}
	// tar.zip に圧縮
	archive.SaveTo(dstFile2 + "del.tar.gz",
		new(CompressionType.GZip) { ArchiveEncoding = new() { Default = Encoding.UTF8 } }); // ファイル名の文字化け対応
}
File.Delete(dstFile2 + "del.tar.tmp");

コメント

タイトルとURLをコピーしました