Zipファイルから内部のエントリファイルの一覧を取得し読み込むという一連の流れ処理を良く行います。
Zipファイルを開く⇒内部のエントリファイルを開くの処理が少し煩わしいので、解決するクラスを作成してみました。
ファイル名:ZipReader.cs
using System.IO.Compression;
namespace CommonLib;
public static class ZipReader
{
public static string JoinEntryPath(string archivePath, string entry)
{
return $"{archivePath}|{entry}";
}
public static (string ArchivePath, string EntryName) ParseEntryPath(string fullPath)
{
var parts = fullPath.Split('|', 2);
return (parts[0], parts[1]);
}
public static List<string> Entries(string archivePath, bool fullPath=true)
{
using var archive = ZipFile.OpenRead(archivePath);
return archive.Entries
.Select(e => fullPath ? JoinEntryPath(archivePath, e.FullName) : e.FullName)
.ToList();
}
public static void OpenEntry(string joinedPath, Action<Stream> action)
{
var (archivePath, entryName) = ParseEntryPath(joinedPath);
using var archive = ZipFile.OpenRead(archivePath);
var entry = archive.GetEntry(entryName)
?? throw new FileNotFoundException($"Entry not found: {entryName}");
using var stream = entry.Open();
action(stream);
}
public static void ForEachEntryStream(string archivePath, Action<string, Stream> action)
{
using var archive = ZipFile.OpenRead(archivePath);
foreach (var entry in archive.Entries)
{
using var stream = entry.Open();
action(entry.FullName, stream);
}
}
}
/*
使用例
string archivePath = @"H:\csharp\console\ZipReader01\sample.zip";
string joinedPath = "";
foreach(var e in ZipReader.Entries(archivePath))
{
if (joinedPath == "") joinedPath = e;
Console.WriteLine($"{e}");
}
Console.WriteLine("");
ZipReader.OpenEntry(joinedPath, stream =>
{
// streamを読み込む処理を行う。
});
Console.WriteLine("");
ZipReader.ForEachEntryStream(archivePath, (name, stream) =>
{
Console.WriteLine($"{name}");
// streamを読み込む処理を行う。
});
結果
H:\csharp\console\ZipReader01\sample.zip|001.PNG
H:\csharp\console\ZipReader01\sample.zip|002.PNG
H:\csharp\console\ZipReader01\sample.zip|003.PNG
001.PNG
002.PNG
003.PNG
*/
デリゲート(Action)を使うことで、ファイルのオープン、クローズ(Dispose)を隠蔽しています。
コメント