JobManager/Archiver/Lib/ArchiveEncoder.cs
2024-06-01 20:41:42 +09:00

187 lines
6.0 KiB
C#

using PacketIO;
namespace Archiver.Lib;
public static class ArchiveEncoder
{
public static async ValueTask Encode(string inputPath, string outputPath)
{
if (!Directory.Exists(inputPath))
{
throw new FileNotFoundException($"{inputPath} does not exist", inputPath);
}
using (FileStream fs = new FileStream(outputPath, FileMode.OpenOrCreate))
{
byte[] buffer = CreateFileHeader();
await fs.WriteAsync(buffer, 0, buffer.Length).ConfigureAwait(false);
FileAttributes attributes = File.GetAttributes(inputPath);
if (attributes.HasFlag(FileAttributes.Directory))
{
DirectoryInfo dirInfo = new DirectoryInfo(inputPath);
PacketDirectoryModel model = await CreatePacketDirectory(dirInfo).ConfigureAwait(false);
try
{
await TreePacketFile.WriteTreeFiles(fs, model.PacketDirectory).ConfigureAwait(false);
}
finally
{
DisposeFiles(model);
}
}
else
{
FileInfo fileInfo = new FileInfo(inputPath);
PacketFileModel model = await CreatePacketFile(fileInfo).ConfigureAwait(false);
try
{
await TreePacketFile.WriteTreeFiles(fs, model.PacketFile).ConfigureAwait(false);
}
finally
{
DisposeFiles(model);
}
}
}
}
public static async ValueTask Encode(IEnumerable<string> inputFiles, string outputPath)
{
using (FileStream fs = new FileStream(outputPath, FileMode.OpenOrCreate))
{
byte[] buffer = CreateFileHeader();
await fs.WriteAsync(buffer, 0, buffer.Length).ConfigureAwait(false);
foreach (string inputPath in inputFiles)
{
FileAttributes attributes = File.GetAttributes(inputPath);
if (attributes.HasFlag(FileAttributes.Directory))
{
DirectoryInfo dirInfo = new DirectoryInfo(inputPath);
PacketDirectoryModel model = await CreatePacketDirectory(dirInfo).ConfigureAwait(false);
try
{
await TreePacketFile.WriteTreeFiles(fs, model.PacketDirectory).ConfigureAwait(false);
}
finally
{
DisposeFiles(model);
}
}
else
{
FileInfo fileInfo = new FileInfo(inputPath);
PacketFileModel model = await CreatePacketFile(fileInfo).ConfigureAwait(false);
try
{
await TreePacketFile.WriteTreeFiles(fs, model.PacketFile).ConfigureAwait(false);
}
finally
{
DisposeFiles(model);
}
}
}
}
}
public static bool IsArchiveFile(string inputPath)
{
FileAttributes attributes = File.GetAttributes(inputPath);
if (attributes.HasFlag(FileAttributes.Directory))
{
return false;
}
using (FileStream fs = File.OpenRead(inputPath))
{
byte[] buffer = new byte[CreateFileHeader().Length];
int c = fs.Read(buffer, 0, buffer.Length);
if (c <= 0)
{
return false;
}
return buffer.SequenceEqual(CreateFileHeader());
}
}
internal static byte[] CreateFileHeader()
{
byte[] header = new byte[]
{
0xCC, 0xDE, 0xFF, 0x00,
};
return header;
}
private static void DisposeFiles(PacketDirectoryModel dirModel)
{
dirModel.PacketDirectory.Dispose();
foreach (PacketDirectoryModel subDirModel in dirModel.Directories)
{
DisposeFiles(subDirModel);
}
foreach (PacketFileModel fileModel in dirModel.Files)
{
DisposeFiles(fileModel);
}
}
private static void DisposeFiles(PacketFileModel fileModel)
{
fileModel.PacketFile.Dispose();
fileModel.TempFile.Dispose();
}
private static async ValueTask<PacketDirectoryModel> CreatePacketDirectory(DirectoryInfo dirInfo)
{
PacketDirectory packetDirectory = new PacketDirectory(dirInfo.Name);
PacketDirectoryModel dirModel = new PacketDirectoryModel()
{
PacketDirectory = packetDirectory,
Files = new List<PacketFileModel>(),
};
foreach (FileInfo fileInfo in dirInfo.EnumerateFiles())
{
PacketFileModel model = await CreatePacketFile(fileInfo).ConfigureAwait(false);
dirModel.Files.Add(model);
packetDirectory.AddFile(model.PacketFile);
}
foreach (DirectoryInfo subInfo in dirInfo.EnumerateDirectories())
{
PacketDirectoryModel subDirModel = await CreatePacketDirectory(subInfo).ConfigureAwait(false);
dirModel.Directories.Add(subDirModel);
packetDirectory.AddFile(subDirModel.PacketDirectory);
}
return dirModel;
}
private static async ValueTask<PacketFileModel> CreatePacketFile(FileInfo fileInfo)
{
TempFile tempFile = new TempFile();
Stream outputStream = tempFile.Open(FileMode.Open);
using (FileStream sourceStream = fileInfo.OpenRead())
{
await sourceStream.CopyToAsync(outputStream).ConfigureAwait(false);
}
outputStream.Seek(0, SeekOrigin.Begin);
PacketFile file = new PacketFile(fileInfo.Name, outputStream);
PacketFileModel model = new PacketFileModel()
{
TempFile = tempFile,
PacketFile = file,
};
return model;
}
}