【问题标题】:Decompress string in c# which were compressed by php's gzcompress()解压c#中由php的gzcompress()压缩的字符串
【发布时间】:2010-11-02 17:23:59
【问题描述】:

我在 c# 4.0 中查询一个 web 服务,它为我提供了一个由 php 的gzcompress() 压缩的字符串。现在我需要在 c# 中解压缩这个字符串。我尝试了几种方法,包括

但每次我得到一个“缺少幻数”异常。

谁能给我一些提示?

谢谢

编辑 1:

我最近的尝试:

public static string Decompress(string compressed) {
    byte[] compressedBytes = Encoding.ASCII.GetBytes(compressed);
    MemoryStream mem = new MemoryStream(compressedBytes);
    GZipStream gzip = new GZipStream(mem, CompressionMode.Decompress);
    StreamReader reader = new StreamReader(gzip);
    return reader.ReadToEnd();
}

【问题讨论】:

  • 代码、代码、代码……还有更多代码。无法修复我们看不到的东西。
  • 这是公共网络服务还是您自己的?你确定你的网络服务的输出是正确的吗?你测试过使用php解压脚本的输出吗?
  • 你做错了。 PHP 的 gzcompress 不返回 ASCII 字符串。
  • 这不是问题。以正确的方式进行操作(我已从 PHP 对其进行 base64 编码并在 C# 中对其进行解码)确实无济于事。

标签: c# php .net compression


【解决方案1】:

好吧,在 @boas.anthro.mnsu.edu 的帮助下,你去吧:

using (var mem = new MemoryStream())
{
    mem.Write(new byte[] { 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00 }, 0, 8);
    mem.Write(inputBytes, 0, inputBytes.Length);

    mem.Position = 0;

    using (var gzip = new GZipStream(mem, CompressionMode.Decompress))
    using (var reader = new StreamReader(gzip))
    {
        Console.WriteLine(reader.ReadToEnd());
    }
}

诀窍是添加一个神奇的标题。请注意,这 不适用于 SharpZipLib。它抱怨没有页脚。但是,.NET 解压缩器可以完美运行。

还有一件事。关于ASCII.GetBytes() 的评论是正确的:您的输入不是ASCII。我通过以下方式实现了这个结果:

// From PHP:

<?php echo base64_encode(gzcompress("Hello world!")); ?>

// In C#:

string input = "eJzzSM3JyVcozy/KSVEEAB0JBF4=";

byte[] inputBytes = Convert.FromBase64String(input);

使用额外的 base64 编码和解码,完美运行。

如果您不能使用 base64 编码,则需要来自 PHP 页面的原始流。您可以使用GetResponseStream()

 var request = WebRequest.Create("http://localhost/page.php");

 using (var response = request.GetResponse())
 using (var mem = response.GetResponseStream())
 {
     // Decompression code from above.
 }

【讨论】:

  • 如果您可以控制 PHP 端,使用 gzencode 代替 gzcompress 将产生具有正确 GZIP 页眉和页脚的输出,而不是让您在 C# 端伪造它。
  • 遗憾的是我对 PHP 端没有任何控制。 ASCII.GetBytes() 还可以吗?
  • 没有。问题是,您从某个地方的 PHP 页面获取数据。我相信你把它当作一个字符串。这是不正确的,您应该将其作为byte[](Memory)Stream 获取。我在答案中添加了一个示例。如果您不知道如何执行此操作并且示例还不够,请将用于读取 PHP 页面的代码添加到文章中,我会就如何更改它提出建议。
【解决方案2】:

我想扩展彼得的答案。 PHP 也可以使用 Deflate 算法进行压缩。在这种情况下,您应该使用 DeflateStream 而不是 GZipStream 并删除前 2 个字节 (HEX: 78 9C) DeflateStream not working with buffer processed from PHP implementation

 private static byte[] Decompress(byte[] data)
{
  using (var compressedStream = new MemoryStream(data.Skip(2).ToArray()))
  using (var zipStream = new DeflateStream(compressedStream, CompressionMode.Decompress))
  using (var resultStream = new MemoryStream())
  {
    zipStream.CopyTo(resultStream);
    return resultStream.ToArray();
  }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-12
    • 2011-11-12
    • 1970-01-01
    • 2013-10-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多