我有一个大的.bak
文件 - 接近12gb。 我需要在代码中将其拆分为多个 2gb.gz
存档。
最大的问题是我需要稍后验证此存档。
你知道就像当你在 3 或 4 个存档上使用 winrar 拆分一个文件时,然后你只需按"解压缩",它就会将它们全部解压缩到一个文件中,或者如果没有足够的档案(你删除一个)就会崩溃。
我需要这样的东西。
public void Compress(DirectoryInfo directorySelected)
{
int writeStat = 0;
foreach (FileInfo fileToCompress in directorySelected.GetFiles())
{
using (FileStream originalFileStream = fileToCompress.OpenRead())
{
if ((File.GetAttributes(fileToCompress.FullName) &
FileAttributes.Hidden) != FileAttributes.Hidden & fileToCompress.Extension != ".gz")
{
bytesToRead = new byte[originalFileStream.Length];
int numBytesRead = bytesToRead.Length;
while (_nowOffset < originalFileStream.Length)
{
writeStat = originalFileStream.Read(bytesToRead, 0, homMuchRead);
using (FileStream compressedFileStream = File.Create(fileToCompress.FullName + counter + ".gz"))
{
using (GZipStream compressionStream = new GZipStream(compressedFileStream,
CompressionMode.Compress))
{
compressionStream.Write(bytesToRead, 0, writeStat);
}
}
_nowOffset = _nowOffset + writeStat;
counter++;
}
FileInfo info = new FileInfo(directoryPath + Path.DirectorySeparatorChar + fileToCompress.Name + ".gz");
//Console.WriteLine($"Compressed {fileToCompress.Name} from {fileToCompress.Length.ToString()} to {info.Length.ToString()} bytes.");
}
}
}
}
它运行良好,但我不知道如何验证他们的计数。
我在测试对象上有 7 个存档。但是如何在一个文件中读取它们,并验证此文件是否已满。
GZip 格式本身不支持您想要的内容。
Zip可以,该功能称为"跨区存档",但.NET的ZipArchive
类则不然。您需要一个第三方库,例如DotNetZip。
但是有解决方法。
创建一个从抽象类继承Stream
类,外部假装它是一个可以写入但不能读取或查找的单个流,在实现中写入多个部分,每个 2GB。在实现中使用 .NET 提供的 FileStream。跟踪班级long
字段中写入的总长度。一旦下一个 Write() 调用超过 2GB,只需写入足够的字节以达到 2GB,关闭并释放底层 FileStream,使用下一个文件名打开另一个文件,将文件长度计数器重置为 0,然后将剩余字节从缓冲区写入 Write() 调用。重复直到关闭。
创建自定义流的实例,传递给 GZipStream 的构造函数,并将完整的 12GB 源数据复制到 GZipStream 中。
如果你做对了,在输出时,你将拥有大小正好为 2GB 的文件(最后一个除外)。
要读取和解压缩它们,您需要使用自定义流实现类似的技巧。编写一个动态连接多个文件的流类,假装它是单个流,但这次你只需要实现Read()
方法。将该串联流从框架提供给GZipStream
。如果您要重新订购或销毁某些部件,则GZipStream
无法解压缩的可能性非常高(但不是 100%),抱怨 CRC 校验和。
附言为了实现和调试上述 2 个流,我建议使用更小的数据集,例如 12 MB 的数据,拆分为 1MB 压缩部分。一旦你让它工作,增加常量并使用完整的 12GB 数据进行测试。