如何将大文件 (12gb) 拆分为多个 1GB 压缩 (.gz) 档案? C#
How to split big file(12gb) into multiple 1GB compressed(.gz) archives? C#
我有一个很大的 .bak
文件 - 将近 12GB。
我需要在代码中将它分成多个 2gb .gz
档案。
最大的问题是我需要稍后验证这个档案。
你知道,当你用 winrar 将一个文件拆分为 3 或 4 个档案时,然后你只需按下 "unpack" 它就会将它们全部解压到一个文件中,或者如果没有足够的档案则崩溃(你删除一个)。
我需要这样的东西。
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
class 没有。为此,您需要一个 third-party 库,例如 DotNetZip.
但有解决方法。
创建一个继承自Stream
抽象的class,对外假装它是一个可以写入但不能读取或查找的单个流,在实现中写入多个部分,2GB /每个。在实现中使用 .NET 提供的 FileStream。在 class 的 long
字段中跟踪写入的总长度。一旦下一个 Write() 调用超过 2GB,写入刚好达到 2GB 的字节,关闭并处理底层 FileStream,打开另一个具有下一个文件名的文件,将文件长度计数器重置为 0,然后写入剩余的从缓冲区到 Write() 调用的字节数。重复直到关闭。
创建自定义流的实例,传递给 GZipStream 的构造函数,并将完整的 12GB 源数据复制到 GZipStream。
如果你做对了,输出的文件大小正好是 2GB(最后一个除外)。
要读取和解压缩它们,您需要使用自定义流实现类似的技巧。编写一个流 class 来动态连接多个文件,假装它是一个流,但这次你只需要实现 Read()
方法。将该连接流提供给框架中的 GZipStream
。如果您重新订购或销毁某些部件,GZipStream
解压缩失败的可能性非常高(但不是 100%),抱怨 CRC 校验和。
P.S。要实施和调试上述 2 个流,我建议使用更小的数据集,例如12 MB 的数据,拆分为 1MB 的压缩块。一旦你让它工作,增加常量并用完整的 12GB 数据进行测试。
我有一个很大的 .bak
文件 - 将近 12GB。
我需要在代码中将它分成多个 2gb .gz
档案。
最大的问题是我需要稍后验证这个档案。
你知道,当你用 winrar 将一个文件拆分为 3 或 4 个档案时,然后你只需按下 "unpack" 它就会将它们全部解压到一个文件中,或者如果没有足够的档案则崩溃(你删除一个)。
我需要这样的东西。
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
class 没有。为此,您需要一个 third-party 库,例如 DotNetZip.
但有解决方法。
创建一个继承自Stream
抽象的class,对外假装它是一个可以写入但不能读取或查找的单个流,在实现中写入多个部分,2GB /每个。在实现中使用 .NET 提供的 FileStream。在 class 的 long
字段中跟踪写入的总长度。一旦下一个 Write() 调用超过 2GB,写入刚好达到 2GB 的字节,关闭并处理底层 FileStream,打开另一个具有下一个文件名的文件,将文件长度计数器重置为 0,然后写入剩余的从缓冲区到 Write() 调用的字节数。重复直到关闭。
创建自定义流的实例,传递给 GZipStream 的构造函数,并将完整的 12GB 源数据复制到 GZipStream。
如果你做对了,输出的文件大小正好是 2GB(最后一个除外)。
要读取和解压缩它们,您需要使用自定义流实现类似的技巧。编写一个流 class 来动态连接多个文件,假装它是一个流,但这次你只需要实现 Read()
方法。将该连接流提供给框架中的 GZipStream
。如果您重新订购或销毁某些部件,GZipStream
解压缩失败的可能性非常高(但不是 100%),抱怨 CRC 校验和。
P.S。要实施和调试上述 2 个流,我建议使用更小的数据集,例如12 MB 的数据,拆分为 1MB 的压缩块。一旦你让它工作,增加常量并用完整的 12GB 数据进行测试。