Files
SteamTools/System.Application.SteamTools.Client.Desktop/TarGZipHelper.cs
T
2021-02-24 18:10:40 +08:00

132 lines
4.9 KiB
C#

using ICSharpCode.SharpZipLib.GZip;
using ICSharpCode.SharpZipLib.Tar;
using ICSharpCode.SharpZipLib.Zip.Compression;
using System.IO;
using System.Text;
using System.Threading.Tasks;
namespace System.Application
{
public static class TarGZipHelper
{
/// <summary>
/// 创建压缩包文件
/// </summary>
/// <param name="filePath">要创建的文件路径</param>
/// <param name="dirPath">要打包的目录</param>
/// <param name="level">压缩等级,取值范围在 <see cref="Deflater.NO_COMPRESSION"/> ~ <see cref="Deflater.BEST_COMPRESSION"/></param>
/// <param name="progressMessage">进度消息监听</param>
/// <returns></returns>
public static bool Create(string filePath, string dirPath, int level = Deflater.BEST_COMPRESSION, ProgressMessageHandler? progress = null)
{
if (!filePath.EndsWith(FileEx.TAR_GZ)) filePath += FileEx.TAR_GZ;
if (File.Exists(filePath)) return false;
if (!Directory.Exists(dirPath)) return false;
using var fs = File.Create(filePath);
using var s = new GZipOutputStream(fs);
s.SetLevel(level);
using var archive = TarArchive.CreateOutputTarArchive(s, TarBuffer.DefaultBlockFactor, Encoding.UTF8);
if (progress != null) archive.ProgressMessageEvent += progress;
HandleFiles(dirPath);
HandleDirs(dirPath);
void HandleFiles(string dirPath_)
{
foreach (var file in Directory.GetFiles(dirPath_))
{
var entry = TarEntry.CreateEntryFromFile(file);
entry.Name = file.TrimStart(dirPath).Trim(Path.DirectorySeparatorChar);
archive.WriteEntry(entry, false);
}
}
void HandleDirs(string dirPath_)
{
foreach (var dir in Directory.GetDirectories(dirPath_))
{
HandleFiles(dir);
}
}
return true;
}
/// <summary>
/// 解压压缩包文件
/// </summary>
/// <param name="filePath">要解压的压缩包文件路径</param>
/// <param name="dirPath">要解压的文件夹路径,文件夹必须不存在</param>
/// <param name="progressMessage">进度消息监听</param>
/// <param name="progress">进度值监听</param>
/// <returns></returns>
public static bool Unpack(string filePath, string dirPath,
ProgressMessageHandler? progressMessage = null,
IProgress<float>? progress = null)
{
if (!File.Exists(filePath)) return false;
if (Directory.Exists(dirPath)) return false;
using var fs = File.OpenRead(filePath);
// 只能用 FileStream 的长度,GZipInputStream.Length 会引发异常
// https://github.com/icsharpcode/SharpZipLib/blob/v1.3.1/src/ICSharpCode.SharpZipLib/Zip/Compression/Streams/InflaterInputStream.cs#L542
float length = fs.Length;
var isFinish = false;
async void ProgressMonitor()
{
while (!isFinish)
{
var value = fs.Position / length;
progress.Report(value);
await Task.Delay(200);
}
}
Directory.CreateDirectory(dirPath);
using var s = new GZipInputStream(fs);
using var archive = TarArchive.CreateInputTarArchive(s, Encoding.UTF8);
if (progressMessage != null) archive.ProgressMessageEvent += progressMessage;
if (progress != null) Task.Factory.StartNew(ProgressMonitor);
archive.ExtractContents(dirPath);
isFinish = true;
progress?.Report(1f);
return true;
}
}
#if DEBUG
[Obsolete("use TarGZipHelper", true)]
public static class ZipHelper
{
[Obsolete("use TarGZipHelper.Create", true)]
public static void PackFiles(string filename, string directory)
{
TarGZipHelper.Create(filename, directory);
}
[Obsolete("use TarGZipHelper.Unpack", true)]
public static bool UnpackFiles(string file, string dir)
{
return TarGZipHelper.Unpack(file, dir);
}
}
[Obsolete("use TarGZipHelper", true)]
public static class ClassZip
{
[Obsolete("use TarGZipHelper.Create", true)]
public static bool Zip(string FileToZip, string ZipedFile, int level)
{
return TarGZipHelper.Create(FileToZip, ZipedFile, level);
}
[Obsolete("use TarGZipHelper.Unpack", true)]
public static void UnZip(string FileToUpZip, string ZipedFolder)
{
TarGZipHelper.Unpack(FileToUpZip, ZipedFolder);
}
}
#endif
}