Files
better-genshin-impact/Build/MicaSetup/Helper/Setup/ArchiveFileHelper.cs

144 lines
5.0 KiB
C#

using MicaSetup.Controls.Animations;
using SharpCompress.Archives.GZip;
using SharpCompress.Archives.Rar;
using SharpCompress.Archives.SevenZip;
using SharpCompress.Archives.Zip;
using SharpCompress.Common;
using SharpCompress.Readers;
using System;
using System.IO;
namespace MicaSetup.Helper;
public static class ArchiveFileHelper
{
public static long TotalUncompressSize(string filePath, ReaderOptions? readerOptions = null!)
{
using dynamic archive = filePath.OpenArchive(readerOptions);
return archive.TotalUncompressSize;
}
public static long TotalUncompressSize(Stream stream, ReaderOptions? readerOptions = null!)
{
using dynamic archive = stream.OpenArchive(readerOptions);
return archive.TotalUncompressSize;
}
public static void ExtractAll(string destinationDirectory, string filePath, ReaderOptions? readerOptions = null!, ExtractionOptions? options = null)
{
using dynamic archive = filePath.OpenArchive(readerOptions);
using IReader reader = archive.ExtractAllEntries();
reader.WriteAllToDirectory(destinationDirectory, options);
}
public static void ExtractAll(string destinationDirectory, Stream stream, Action<double, string> progressCallback = null!, ReaderOptions? readerOptions = null!, ExtractionOptions? options = null)
{
using dynamic archive = stream.OpenArchive(readerOptions);
using IReader reader = archive.ExtractAllEntries();
using ProgressAccumulator acc = new(anime: DoubleEasingAnimations.EaseInOutCirc);
long currentTotalSize = default;
double currentProgress = default;
string currentKey = null!;
void ProgressCallback(double progress)
{
if (currentProgress != progress || currentKey != reader.Entry.Key)
{
progressCallback?.Invoke(currentProgress = progress, currentKey = reader.Entry.Key);
}
}
while (reader.MoveToNextEntry())
{
ProgressCallback(Math.Min(currentTotalSize / (double)archive.TotalUncompressSize, 1d));
if ((reader.Entry.Size / 1048576d) > 1d)
{
_ = acc.Reset(Math.Min(currentTotalSize / (double)archive.TotalUncompressSize, 1d),
Math.Min((currentTotalSize + reader.Entry.Size) / (double)archive.TotalUncompressSize, 1d),
reader.Entry.Size / 8912.896,
ProgressCallback
).Start();
}
reader.WriteEntryToDirectory(destinationDirectory, options);
acc.Stop();
currentTotalSize += reader.Entry.Size;
ProgressCallback(Math.Min(currentTotalSize / (double)archive.TotalUncompressSize, 1d));
}
}
}
file enum ArchiveFileType
{
Unknown,
SevenZip,
Zip,
Rar,
GZip,
}
file static class ArchiveFileHelperExtension
{
public static ArchiveFileType GetArchiveType(this Stream stream)
{
byte[] header = new byte[3];
stream.Read(header, 0, header.Length);
if (header[0] == 0x37 && header[1] == 0x7A)
{
return ArchiveFileType.SevenZip;
}
else if (header[0] == 0x50 && header[1] == 0x4B)
{
return ArchiveFileType.Zip;
}
else if (header[0] == 0x52 && header[1] == 0x61 && header[2] == 0x72)
{
return ArchiveFileType.Rar;
}
else if (header[0] == 0x1F && header[1] == 0x8B)
{
return ArchiveFileType.GZip;
}
return ArchiveFileType.Unknown;
}
public static ArchiveFileType GetArchiveType(this string filePath)
{
using Stream fileStream = filePath.OpenRead();
return GetArchiveType(fileStream);
}
public static Stream OpenRead(this string filePath)
{
return new FileStream(filePath, FileMode.Open, FileAccess.Read);
}
public static dynamic OpenArchive(this string filePath, ReaderOptions? readerOptions = null!)
{
ArchiveFileType type = filePath.GetArchiveType();
dynamic? archive = type switch
{
ArchiveFileType.Zip => ZipArchive.Open(filePath, readerOptions),
ArchiveFileType.GZip => GZipArchive.Open(filePath, readerOptions),
ArchiveFileType.Rar => RarArchive.Open(filePath, readerOptions),
ArchiveFileType.SevenZip or _ => SevenZipArchive.Open(filePath, readerOptions),
};
return archive;
}
public static dynamic OpenArchive(this Stream stream, ReaderOptions? readerOptions = null!)
{
ArchiveFileType type = stream.GetArchiveType();
using dynamic? archive = type switch
{
ArchiveFileType.Zip => ZipArchive.Open(stream, readerOptions),
ArchiveFileType.GZip => GZipArchive.Open(stream, readerOptions),
ArchiveFileType.Rar => RarArchive.Open(stream, readerOptions),
ArchiveFileType.SevenZip or _ => SevenZipArchive.Open(stream, readerOptions),
};
return archive;
}
}