简体   繁体   English

GzipStream 分块压缩导致文件损坏

[英]GzipStream blockwise compression results in a corrupted file

I am trying to implement block-by-block compression using GzipStream class.我正在尝试使用 GzipStream 类实现逐块压缩。 .NET Core 3.1, Visual Studio 2019, Console App. .NET Core 3.1、Visual Studio 2019、控制台应用程序。 My OS is Windows 10. I believe it should be possible because gzip files consist of independent blocks one after another as per format specification.我的操作系统是 Windows 10。我相信这应该是可能的,因为 gzip 文件按照格式规范由一个接一个的独立块组成。 But resulting files that I get are corrupted.但是我得到的结果文件已损坏。 Here's the code:这是代码:

using System;
using System.Globalization;
using System.IO;
using System.IO.Compression;

namespace GzipToMemoryStreamExample
{
class Program
{
    private static int blockSize;
    private static string sourceFileName = "e:\\SomeFolder\\SomeFile.ext";

    private static byte[] currentBlock;
    private static FileStream readingStream;
    private static FileStream writingStream;

    static void Main(string[] args)
    {
        Console.WriteLine("Enter block size:");
        string blockSizeStr = Console.ReadLine();
        int.TryParse(blockSizeStr, out blockSize);

        readingStream = new FileStream(sourceFileName, FileMode.Open);
        string resultingFileName = Path.ChangeExtension(sourceFileName, ".gz");
        CreateAndOpenResultingFile(resultingFileName);
        while (ReadBlock())
        {
            byte[] processedBlock = ProcessBlock(currentBlock);
            writingStream.Write(processedBlock, 0, processedBlock.Length);
        }
        readingStream.Dispose();
        writingStream.Dispose();
        Console.WriteLine("Finished.");
        Console.ReadKey();
    }

    private static bool ReadBlock()
    {
        bool result;
        int bytesRead;
        currentBlock = new byte[blockSize];
        bytesRead = readingStream.Read(currentBlock, 0, blockSize);
        result = bytesRead > 0;
        return result;
    }

    private static byte[] ProcessBlock(byte[] sourceData)
    {
        byte[] result;
        using (var outputStream = new MemoryStream())
        {
            using var compressionStream = new GZipStream(outputStream, CompressionMode.Compress);
            compressionStream.Write(sourceData, 0, sourceData.Length);
            result = outputStream.ToArray();
        }
        return result;
    }

    private static void CreateAndOpenResultingFile(string fileName)
    {
        if (File.Exists(fileName))
        {
            File.Delete(fileName);
        }
        writingStream = File.Create(fileName);
    }
}
}

When I look at resulting files I see that result somehow depends on block size I choose.当我查看结果文件时,我发现结果在某种程度上取决于我选择的块大小。 if it's smaller than ~100 Kb, resulting "compressed" blocks are of 10 bytes size each, which leads to extremely small useless file.如果它小于 ~100 Kb,则生成的“压缩”块每个大小为 10 字节,这会导致非常小的无用文件。 If size of block is greater than ~100 Kb, then the size of file becomes reasonably large, about 80% of the original, but still corrupted.如果块的大小大于 ~100 Kb,则文件的大小会变得相当大,大约是原始大小的 80%,但仍然损坏。
Also I checked the block headers and it turns out they're strange.我还检查了块标题,结果发现它们很奇怪。 OS is set to TOPS-20 (0x0a value), ISIZE at the end of block is always totally wrong. OS 设置为 TOPS-20(0x0a 值),块末尾的 ISIZE 总是完全错误的。

What is my mistake?我的错误是什么?

It's solved just with moving result = outputStream.ToArray();它只是通过移动result = outputStream.ToArray();解决的 line out of the compressionStream using scope as Mark Adler suggested in the comments.正如 Mark Adler 在评论中建议的那样,使用范围从compressionStream 中排除。

    private static byte[] ProcessBlock(byte[] sourceData)
    {
        byte[] result;
        using (var outputStream = new MemoryStream())
        {
            using (var compressionStream = new GZipStream(outputStream, CompressionMode.Compress))
            {
                compressionStream.Write(sourceData, 0, sourceData.Length);
            }
            result = outputStream.ToArray();
        }
        return result;
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM