使用Compression.DeflateStream压缩和解压缩Stream

gre*_*ner 19 .net c# compression stream

我正在尝试使用Compression.DeflateStream压缩和解压缩Stream .压缩似乎工作正常,因为下面的代码将我的Stream压缩为一个110字节长的数组.但是,读取解压缩的Stream会导致空字符串.

class Program
{
    static void Main(string[] args)
    {
        // Compress a random string value
        string value = Path.GetRandomFileName();
        byte[] compressedBytes;

        using (var writer = new StreamWriter(new MemoryStream()))
        {
            writer.Write(value);
            writer.Flush();
            writer.BaseStream.Position = 0;

            compressedBytes = Compress(writer.BaseStream);
        }

        // Decompress compressed bytes
        Stream decompressedStream = Decompress(compressedBytes);
        // here already applies: decompressedStream.Length == 0

        using (var reader = new StreamReader(decompressedStream))
        {
            string decompressedValue = reader.ReadToEnd();

            if (value == decompressedValue)
                Console.WriteLine("Success");
            else
                Console.WriteLine("Failed");
        }
    }

    private static byte[] Compress(Stream input)
    {
        using (var compressStream = new MemoryStream())
        using (var compressor = new DeflateStream(compressStream, CompressionMode.Compress))
        {
            input.CopyTo(compressor);
            return compressStream.ToArray();
        }
    }

    private static Stream Decompress(byte[] input)
    {
        var output = new MemoryStream();

        using (var compressStream = new MemoryStream(input))
        using (var decompressor = new DeflateStream(compressStream, CompressionMode.Decompress))
            decompressor.CopyTo(output);

        output.Position = 0;
        return output;
    }
}
Run Code Online (Sandbox Code Playgroud)

任何人都可以帮我这个吗?非常感谢.

max*_*max 31

修复你的Compress功能:

private static byte[] Compress(Stream input)
{
    using(var compressStream = new MemoryStream())
    using(var compressor = new DeflateStream(compressStream, CompressionMode.Compress))
    {
        input.CopyTo(compressor);
        compressor.Close();
        return compressStream.ToArray();
    }
}
Run Code Online (Sandbox Code Playgroud)

在返回结果字节数组之前,未刷新压缩流.

  • @Luke:来自[DeflateStream.Flush()`]的文档(https://msdn.microsoft.com/en-us/library/system.io.compression.deflatestream.flush(v = vs.110). aspx):_"此方法的当前实现不会刷新内部缓冲区.当对象被释放时,内部缓冲区被刷新."_至于为什么这是设计,`Stream.Flush()`意图刷新内部缓冲,但是在知道你在_end_之前无法完成一个deflate流,这只有当流是_closed_时才有可能. (6认同)
  • 必须要注意的是,如果你打电话给'Flush`而不是'Close`它就行不通.我认为`Close`在内部调用'Flush`就是为什么这有效,但不是. (4认同)
  • 考虑到您无论如何都在使用 `using`,因此不需要 `Flush()`˛ 或 `Close()`。只需将 `ToArray()` 调用移动到 `using` 之后。一切都会自动完成。 (2认同)

Dar*_*rov 11

尝试关闭流:

class Program
{
    static void Main(string[] args)
    {
        // Compress a random string value
        string value = DateTime.Now.ToLongTimeString();
        byte[] compressedBytes;

        using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(value)))
        {
            compressedBytes = Compress(stream);
        }


        // Decompress compressed bytes
        using (var decompressedStream = Decompress(compressedBytes))
        using (var reader = new StreamReader(decompressedStream))
        {
            string decompressedValue = reader.ReadToEnd();

            if (value == decompressedValue)
                Console.WriteLine("Success");
            else
                Console.WriteLine("Failed");
        }
    }

    public static byte[] Compress(Stream input)
    {
        using (var compressedStream = new MemoryStream())
        using (var zipStream = new GZipStream(compressedStream, CompressionMode.Compress))
        {
            input.CopyTo(zipStream);
            zipStream.Close();
            return compressedStream.ToArray();
        }
    }

    public static Stream Decompress(byte[] data)
    {
        var output = new MemoryStream();
        using(var compressedStream = new MemoryStream(data))
        using(var zipStream = new GZipStream(compressedStream, CompressionMode.Decompress))
        {
            zipStream.CopyTo(output);
            zipStream.Close();
            output.Position = 0;
            return output;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)


小智 8

所有这些答案都远离理想形式,因为你们都忘了"使用"处理和关闭流意味着不需要额外的Close().我认为理想的代码将是这样的:

public static class CompressionHelper
{
    public static byte[] Compress(byte[] data)
    {
        byte[] compressArray = null;
        try
        {
            using (MemoryStream memoryStream = new MemoryStream())
            {
                using (DeflateStream deflateStream = new DeflateStream(memoryStream, CompressionMode.Compress))
                {
                    deflateStream.Write(data, 0, data.Length);
                }
                compressArray = memoryStream.ToArray();
            }
        }
        catch (Exception exception)
        {
            // do something !
        }
        return compressArray;
    }

    public static byte[] Decompress(byte[] data)
    {
        byte[] decompressedArray = null;
        try
        {
            using (MemoryStream decompressedStream = new MemoryStream())
            {
                using (MemoryStream compressStream = new MemoryStream(data))
                {
                    using (DeflateStream deflateStream = new DeflateStream(compressStream, CompressionMode.Decompress))
                    {
                        deflateStream.CopyTo(decompressedStream);
                    }
                }
                decompressedArray = decompressedStream.ToArray();
            }
        }
        catch (Exception exception)
        {
            // do something !
        }

        return decompressedArray;
    }
}
Run Code Online (Sandbox Code Playgroud)