如何将大文件(12gb)分成多个1GB压缩(.gz)存档? C#

时间:2019-07-18 19:15:30

标签: c# archive

我有一个大的.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个存档。但是如何在一个文件中读取它们,并验证该文件已满。

1 个答案:

答案 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数据进行测试。