【问题标题】:GZipStream and decompressionGZipStream 和解压
【发布时间】:2009-10-17 07:58:42
【问题描述】:

我有应该进行压缩的代码:

FileStream fs = new FileStream("g:\\gj.txt", FileMode.Open);
FileStream fd = new FileStream("g:\\gj.zip", FileMode.Create);
GZipStream csStream = new GZipStream(fd, CompressionMode.Compress);

byte[] compressedBuffer = new byte[500];
int offset = 0;
int nRead;

nRead = fs.Read(compressedBuffer, offset, compressedBuffer.Length);
while (nRead > 0)
{
    csStream.Write(compressedBuffer, offset, nRead);
    offset = offset + nRead;
    nRead = fs.Read(compressedBuffer, offset, compressedBuffer.Length);
}

fd.Close();
fs.Close();

我认为确实如此,但我想解压缩上面压缩的内容。我有这样的想法:

FileStream fd = new FileStream("g:\\gj.new", FileMode.Create);
FileStream fs = new FileStream("g:\\gj.zip", FileMode.Open);
GZipStream csStream = new GZipStream(fs, CompressionMode.Decompress);

byte[] decompressedBuffer = new byte[500];
int offset = 0;
int nRead;

nRead=csStream.Read(decompressedBuffer, offset, decompressedBuffer.Length);
while (nRead > 0)
{
    fd.Write(decompressedBuffer, offset, nRead);
    offset = offset + nRead;
    nRead = csStream.Read(decompressedBuffer, offset, decompressedBuffer.Length);
}

fd.Close();
fs.Close();

在这里它没有...在进入循环之前我有 nRead = 0...我做错了什么? 我使用的测试文件是最简单的TEXT文件(大小:104字节)...

【问题讨论】:

  • 编辑答案以显示读写
  • 还要注意 gzip != ".zip"
  • (注意我在发布后修复了一个错误;检查两个while 仅在顶行循环Read(不在底部)。

标签: c# gzipstream compression


【解决方案1】:

我的第一个想法是你还没有关闭csStream。如果您使用using,这会自动发生。由于 gzip 缓冲数据,您可能会丢失一些数据。

其次;不要增加offset;这是 buffer(不是流)中的偏移量。 0点离开:

using (Stream fs = File.OpenRead("gj.txt"))
using (Stream fd = File.Create("gj.zip"))
using (Stream csStream = new GZipStream(fd, CompressionMode.Compress))
{
    byte[] buffer = new byte[1024];
    int nRead;
    while ((nRead = fs.Read(buffer, 0, buffer.Length))> 0)
    {
        csStream.Write(buffer, 0, nRead);
    }
}

using (Stream fd = File.Create("gj.new.txt"))
using (Stream fs = File.OpenRead("gj.zip"))
using (Stream csStream = new GZipStream(fs, CompressionMode.Decompress))
{
    byte[] buffer = new byte[1024];
    int nRead;
    while ((nRead = csStream.Read(buffer, 0, buffer.Length)) > 0)
    {
        fd.Write(buffer, 0, nRead);
    }
}

【讨论】:

  • 问题是commression运行良好,但无法解压。
  • 您也可以使用内置的 .CopyTo() 函数来代替缓冲区循环。在这种情况下,它将是:csStream.CopyTo(fd);
  • @JamesR - 不是在写这个答案时,我不能;p
  • 好点,只是增加了这一点知识。我在 GZipStream 中发现的另一件烦人的事情。如果要写入 MemoryStream,则必须 .Close() GZipStream。否则它将保留最后几个字节。 .Flush() 似乎没有完成这项工作。 (如果你在 using 语句中使用 MemoryStream。)
  • @James 确实如此,但这是 GZIP 本身的副作用;并且至少您可以选择(在构造函数中)让这个 not 关闭底层流。顺便说一句,它会影响所有目的地 - 不仅仅是 MemoryStream。
【解决方案2】:

我有两种方法,就像 James Roland 提到的那样。

private static byte[] Compress(HttpPostedFileBase file)
{
    using var to = new MemoryStream();
    using var gZipStream = new GZipStream(to, CompressionMode.Compress);
    file.InputStream.CopyTo(gZipStream);
    gZipStream.Flush();
    return to.ToArray();
}

private static byte[] Decompress(byte[] compressed)
{
    using var from = new MemoryStream(compressed);
    using var to = new MemoryStream();
    using var gZipStream = new GZipStream(from, CompressionMode.Decompress);
    gZipStream.CopyTo(to);
    return to.ToArray();
}

但是,我使用的是上传

Request.Files[0] 

然后压缩并保存在数据库中。然后我把img拉出来,解压并设置一个src

$"data:image/gif;base64,{ToBase64String(Decompress(img))}";

【讨论】:

  • 永远不要在没有using的情况下使用IDisposable对象!
  • @JCKödel 虽然它显然更愿意在可能的情况下利用using,但说“从不”是不准确的,而且在很多情况下是不希望和/或不可能的。
  • 如果您没有利用 IDisposable 并使用语法,那么建议确保使用 try/catch/finally 并且不要在函数之间传递流(如果可以避免的话)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-09-21
  • 1970-01-01
相关资源
最近更新 更多