我有一个大的.bak
文件-接近12GB。
我需要将其拆分为代码中的多个2gb .gz
存档。
最大的问题是我以后需要验证此存档。
您知道当您使用Winrar在3个或4个压缩文件上分割一个文件,然后按“解压”,它将全部解压缩为一个文件,或者如果没有足够的压缩文件则崩溃(删除一个)
我需要这样的东西。
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个存档。但是如何在一个文件中读取它们,并验证该文件已满。
答案 0 :(得分:0)
GZip格式本身不支持您想要的内容。
Zip确实如此,该功能称为“跨区存档”,但.NET中的ZipArchive
类却没有。为此,您需要一个第三方库,例如DotNetZip。
但是有解决方法。
创建一个继承自Stream
抽象类的类,到外面,它是一个可以写入但不能读取或查找的单一流,在实现中写入多个片段,每个2GB。在实现中使用.NET提供的FileStream。在班级的long
字段中跟踪编写的总长度。下一个Write()调用将超过2GB,立即写入足够的字节以达到2GB,关闭并处置基础FileStream,使用下一个文件名打开另一个文件,将文件长度计数器重置为0,然后写入剩余的字节缓冲区中的字节数,再调用Write()。重复直到关闭。
创建您的自定义流的实例,传递给GZipStream的构造函数,然后将完整的12GB源数据复制到GZipStream中。
如果操作正确,则输出的文件大小恰好为2GB(最后一个除外)。
要读取和解压缩它们,您需要使用自定义流实施类似的技巧。编写一个流类,将多个文件动态地连接起来,假装它是单个流,但是这次您只需要实现Read()
方法。将该连接流从框架提供给GZipStream
。如果您要重新订购或销毁某些零件,则GZipStream
很有可能无法解压缩,而抱怨CRC校验和的可能性非常高(但不是100%)。
P.S。要实现和调试上述2个流,我建议使用更小的数据集,例如12 MB的数据,分成1MB的压缩块。一旦可以使用,请增加常量并使用完整的12GB数据进行测试。