如何使用gzipstream将内存流压缩为内存流?

时间:2018-08-23 15:38:38

标签: c#

你好,我的问题是,如果可能,我需要将带有GZipStream的MemoryStream压缩到MemoryStream中,并压缩到该方法作为参数获取的同一MemoryStream中。如果无法做到这一点,那么我该如何做到这一点,以使其最有效地利用内存。


这是我当前的方法,它给了我 System.NotSupportedException:'Stream不支持读取。'用于compress.CopyTo

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

1 个答案:

答案 0 :(得分:0)

您无法将流复制到其自身,至少没有很多工作是不可能的。仅为压缩的数据分配一个新的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;
}