首页 > 解决方案 > 如何使用 gzipstream 将内存流压缩成内存流?

问题描述

您好,我的问题是,如果可能的话,我需要将 MemoryStream 和 GZipStream 压缩到 MemoryStream 中,然后压缩到该方法作为参数获取的相同 MemoryStream 中。如果这不能实现,我怎么能做到,所以它是最有效的内存。


这是我当前的方法,它给了我System.NotSupportedException: 'Stream does not support reading。用于 compress.CopyTo

public static void GZipCompress(MemoryStream memoryStream)
{
    using (GZipStream compress = new GZipStream(memoryStream, CompressionMode.Compress))
    {
        compress.CopyTo(memoryStream);
    }
}

标签: c#

解决方案


您不能将流复制到自身,至少在没有大量工作的情况下不能。只需为压缩数据分配一个新的 MemoryStream 就很简单且相当有效。例如

public MemoryStream GZipCompress(MemoryStream memoryStream)
{
    var newStream = new MemoryStream((int)memoryStream.Length / 2); //set to estimate of compression ratio

    using (GZipStream compress = new GZipStream(newStream, CompressionMode.Compress))
    {
        memoryStream.CopyTo(compress);
    }
    newStream.Position = 0;
    return newStream;
}

这是关于如何执行 MemoryStream 的就地压缩的未经测试的想法。

public void GZipCompress(MemoryStream memoryStream)
{
    var buf = new byte[1024 * 64];
    int writePos = 0;

    using (GZipStream compress = new GZipStream(memoryStream, CompressionMode.Compress))
    {
        while (true)
        {
            var br = compress.Read(buf, 0, buf.Length);
            if (br == 0) //end of stream
            {
                break;
            }
            var readPos = memoryStream.Position;
            memoryStream.Position = writePos;
            memoryStream.Write(buf, 0, br);
            writePos += br;

            if (memoryStream.Position > readPos)
            {
                throw new InvalidOperationException("Overlapping writes corrupted the stream");
            }
            memoryStream.Position = readPos;
        }
    }
    memoryStream.SetLength(writePos);
    memoryStream.Position = 0;
}

推荐阅读