【问题标题】:How to compress memory stream into memory stream using gzipstream?如何使用 gzipstream 将内存流压缩成内存流?
【发布时间】:2019-01-30 01:13:57
【问题描述】:

您好,我的问题是,如果可能的话,我需要将 MemoryStream 和 GZipStream 压缩到 MemoryStream 中,然后压缩到该方法作为参数获取的相同 MemoryStream 中。如果这无法实现,我该如何做到这一点,这样它是最节省内存的。


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

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

【问题讨论】:

  • 最高效的内存可能会完全避免输出内存流。您是否要将压缩数据流式传输到其他地方,例如文件、套接字或字符串?然后直接使用它而不是内存中间体。 (当然,这同样适用于输入。)
  • 我必须将 MemoryStream 放入正在写入 Ftp 的 Stream。

标签: c#


【解决方案1】:

您不能将流复制到自身,至少在没有很多 工作的情况下是这样。只需为压缩数据分配一个新的 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;
}

【讨论】:

  • 但是我会在内存中有 2 个内存流,不是吗?如果它们很大怎么办?
  • 那么你会有两个大流:)。如果您真的想要,您可能会重用主流。如果任何数据块无法实际压缩,它就会爆炸,就像数学上某些块必须的那样。但请参阅编辑。
  • 感谢您的帮助:)
  • 我尝试了您的代码,而不是用压缩的代码替换 memoryStream,而是您的第一个 sn-p,它仍然给我错误 System.NotSupportedException: 'Stream does not support reading。' compress.CopyTo(newStream);
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-11-29
  • 1970-01-01
  • 2014-05-01
  • 2017-08-06
相关资源
最近更新 更多