【问题标题】:C#: Deflating XML gives different result than doing it in JavaScriptC#:对 XML 进行放气会产生与在 JavaScript 中放气不同的结果
【发布时间】:2018-06-26 07:29:10
【问题描述】:

我正在尝试在 C# 中压缩 xml 并将其编码为 base64。我尝试同时使用 DeflateStream 和 GZipStream 但我得到的结果似乎与在节点库中使用不同。
我将发布节点代码和c#代码:

//zlib = require('zlib');
zlib.deflateRaw(xml, (function(_this) {
      return function(err, deflated) {
             return deflated.toString('base64');
      }
} 

C# DeflateStream

 private static byte[] Deflate(String str)
    {
      using (MemoryStream output = new MemoryStream())
      {
        using (DeflateStream gzip =
          new DeflateStream(output, CompressionMode.Compress))
        {
          using (StreamWriter writer =
            new StreamWriter(gzip, System.Text.Encoding.UTF8))
          {
            writer.Write(str);
          }
        }

        return output.ToArray();
      }
    }

C# GZipStream

public static byte[] Zip(string str)
{
      var bytes = Encoding.UTF8.GetBytes(str);

      using (var msi = new MemoryStream(bytes))
      using (var mso = new MemoryStream())
      {
        using (var gs = new GZipStream(mso, CompressionMode.Compress))
        {
          //msi.CopyTo(gs);
          CopyTo(msi, gs);
        }

        return mso.ToArray();
      }
 }

C# Base64 编码:

private static string Base64Encode(byte[] textBytes)
{
   return System.Convert.ToBase64String(textBytes);
} 

我有什么遗漏吗?

更新

我找到了一个有效的例子。通过使用它,我还可以使用 Node.js 对其进行解码。

 var bytes = Encoding.UTF8.GetBytes(stringToDeflate);
  using (var output = new MemoryStream())
  {
    using (var zip = new DeflateStream(output, CompressionMode.Compress))
    {
      zip.Write(bytes, 0, bytes.Length);
    }
    var base64 = Convert.ToBase64String(output.ToArray());
  }

更新 2(工作代码 - 供未来的搜索者使用)

private static string DeflateAndEncode(string str)
    {
      var bytes = Encoding.UTF8.GetBytes(str);
      using (var output = new MemoryStream())
      {
        using (var zip = new DeflateStream(output, CompressionMode.Compress))
        {
          zip.Write(bytes, 0, bytes.Length);
        }
        var base64 = Convert.ToBase64String(output.ToArray());

        return base64;
      }
    }

    private static string DecodeAndInflate(string str)
    {
      var utf8 = Encoding.UTF8;
      var bytes = Convert.FromBase64String(str);
      using (var output = new MemoryStream())
      {
        using (var input = new MemoryStream(bytes))
        {
          using (var unzip = new DeflateStream(input, CompressionMode.Decompress))
          {
            unzip.CopyTo(output, bytes.Length);
            unzip.Close();
          }
          return utf8.GetString(output.ToArray());
        }
      }
    }

【问题讨论】:

  • 很确定这是一个编码问题。可以试试new StreamWriter(gzip) 代替 UTF-8 编码吗?
  • @bommelding Node 输出中的 513 个字符和 C# 实现中的 537 个字符
  • 添加了一个似乎有效的更新。
  • @bommelding 我发现的一个区别(但我不确定它是否有所不同)不是工作不使用 StreamWriter。
  • public static void CopyTo(Stream src, Stream dest) { byte[] bytes = new byte[4096];诠释cnt; while ((cnt = src.Read(bytes, 0, bytes.Length)) != 0) { dest.Write(bytes, 0, cnt); } }

标签: c# node.js zip saml-2.0


【解决方案1】:

用于 base-64 编码的字符在 C# 和 Node.js 之间有所不同。

C# uses the following:

base-64位从0升序依次为大写字母“A”到“Z”,小写字母“a”到“z”,数字“0”到“9”,符号“ +”和“/”。无值字符“=”用于尾随填充。

Node.js 使用 RFC4648 第 5 节中指定的 "The "URL and Filename safe" Base 64 Alphabet"

A-Z, a-z, 0-9, - (minus), _ (underscore)
Trailing padding uses '='

所以你试图做的不会奏效。

您可以通过将_- 字符分别替换为+/ 来修复它,以将C# 编码转换为Node.js,反之亦然,然后再对数据进行base64 解码。

【讨论】:

  • 但这并不能说明长度的差异。
  • @Matthew Watson,这个改动应该在原文中做吗?因为否则我在放气后有一个字节数组。
  • 您能举例说明字符串有什么不同吗?我尝试了“testcode!!!/+_-”,但得到了预期的(相等的)结果。这是我的NodeJSFiddler 和我的C#.NET Fiddler
  • @Freggar 您对测试代码的 base64 输入不包含不同的字符。尝试将其用作您的二进制数据:Enumerable.Range(0, 255).Select(x => (byte)x).ToArray()
  • 奇怪,我仍然得到相同的结果(我更新了我的提琴手链接)
猜你喜欢
  • 1970-01-01
  • 2016-07-05
  • 2021-02-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-07-06
  • 1970-01-01
  • 2012-02-11
相关资源
最近更新 更多