AS3 中的 "ByteArray.uncompress()" 相当于 C# 中的什么?

What is "ByteArray.uncompress()" in AS3 equivalent to in C#?

我正在尝试将 AS3 (ActionScript 3) 函数转换为 C#。

此 ActionScript 函数包含一个名为 ByteArray 的 class,据我所知,它基本上听起来像 lmao。我认为这有点类似于 byte[] 在 C# 中的表现。不管怎样,我已尽力使用 MemoryStream 将代码转换为 C#,然后向其写入字节,然后返回 UTF8 字符串,如您在下面的代码中所见。但是,我觉得我处理 ActionScript 代码的方式似乎不准确,这就是我上面的问题所在。

将负数写入 "loc1" (The ByteArray) 和 "loc1.uncompress()",这就是我觉得自己失败的地方,想知道是否有人可以帮助我转换这个函数,所以完全准确吗?

除了这个问题之外,我还想问一下,我在 C# 代码中对负数所做的处理是否与 ActionScript 代码的处理方式一样正确?意义重大 (:

(抱歉,如果不能完全理解,如果我说的不太相符)

ActionScript 代码:

private function p() : String
      {
         var _loc1_:ByteArray = new ByteArray();
         _loc1_.writeByte(120);
         _loc1_.writeByte(-38);
         _loc1_.writeByte(99);
         _loc1_.writeByte(16);
         _loc1_.writeByte(12);
         _loc1_.writeByte(51);
         _loc1_.writeByte(41);
         _loc1_.writeByte(-118);
         _loc1_.writeByte(12);
         _loc1_.writeByte(50);
         _loc1_.writeByte(81);
         _loc1_.writeByte(73);
         _loc1_.writeByte(49);
         _loc1_.writeByte(-56);
         _loc1_.writeByte(13);
         _loc1_.writeByte(48);
         _loc1_.writeByte(54);
         _loc1_.writeByte(54);
         _loc1_.writeByte(14);
         _loc1_.writeByte(48);
         _loc1_.writeByte(46);
         _loc1_.writeByte(2);
         _loc1_.writeByte(0);
         _loc1_.writeByte(45);
         _loc1_.writeByte(-30);
         _loc1_.writeByte(4);
         _loc1_.writeByte(-16);
         _loc1_.uncompress();
         _loc1_.position = 0;
         return _loc1_.readUTF();
      }

我的 C# 代码:

public string p()
        {
            MemoryStream loc1 = new MemoryStream();
            loc1.WriteByte((byte)120);
            loc1.WriteByte((byte)~-38);
            loc1.WriteByte((byte)99);
            loc1.WriteByte((byte)16);
            loc1.WriteByte((byte)12);
            loc1.WriteByte((byte)51);
            loc1.WriteByte((byte)41);
            loc1.WriteByte((byte)~-118);
            loc1.WriteByte((byte)12);
            loc1.WriteByte((byte)50);
            loc1.WriteByte((byte)81);
            loc1.WriteByte((byte)73);
            loc1.WriteByte((byte)49);
            loc1.WriteByte((byte)~-56);
            loc1.WriteByte((byte)13);
            loc1.WriteByte((byte)48);
            loc1.WriteByte((byte)54);
            loc1.WriteByte((byte)54);
            loc1.WriteByte((byte)14);
            loc1.WriteByte((byte)48);
            loc1.WriteByte((byte)46);
            loc1.WriteByte((byte)2);
            loc1.WriteByte((byte)0);
            loc1.WriteByte((byte)45);
            loc1.WriteByte((byte)~-30);
            loc1.WriteByte((byte)4);
            loc1.WriteByte((byte)~-16);
            loc1.Position = 0;
            return Encoding.UTF8.GetString(loc1.ToArray());
        }

1) 在 C# 中,字节是无符号的。您不能使用补码将有符号字节转换为无符号字节,因为您的意图是按位表示应该相同,而不是相反,这就是补码的作用。

一种简单的转换方法是使用 0xFF 进行屏蔽:-37 & 0xFF = 219。还有其他数学上等效的方法,例如使用 sbyte sb = -37; byte b = sb < 0 ? 256 + sb : sb;

检查负数

2) 内置的 System.IO.Compression 命名空间在很多方面都缺乏。一方面,它甚至不支持解压缩 zlib 数据,这是您的字节数组所包含的。最好的方法是在 Nuget 上使用第三方包。 DotNetZip 库可以满足您的需求,特别是 Ionic.Zlib.ZlibStream.UncompressBuffer 函数。

(1)
@Jimmy 给了你一个很好的答案。
这就是他告诉你 "to mask with 0xFF" 的意思,这样你的 -38 就变成了:

loc1.WriteByte( (byte)(-38 & 0xFF) );

对具有负 sign 的任何其他值执行相同的上述逻辑。

(2)
如果您只使用 hex 而不是 decimal 编写的值,可能会更容易。这意味着你写的不是十进制 255 而是 0xFF 的等效十六进制,因为字节应该是十六进制的。 WriteByte 是 auto-converting 你的小数,但它不能帮助你了解它是怎么回事...

例如,您的开头两个字节值为 120 -38,但在十六进制中为 0x78 0xDA
现在如果你 google 搜索 bytes 0x78 0xDA 你会发现这两个字节是 header ZLIB 的 DEFLATE 压缩算法。

了解此 ZLIB 详细信息对于下一步很重要...

(3)
有时变量名 在 de-compiling 期间并不总是恢复。这就是为什么您的所有代码都将这些愚蠢的 _loc_ 作为通用名称(真正的 var 名称未知,只有它们的数据类型)。

您的 _loc1_.uncompress(); 应该包含指定算法的 String 变量。

public function uncompress(algorithm:String) :void //from AS3 documentation

在反编译过程中丢失了重要信息。幸运的是,只有 "ZLIB"、“DEFLATE”或“LZMA”这三个选项。从上面的通知(2)可以看出应该是_loc1_.uncompress("DEFLATE");

解法:

创建字节数组(不是内存流)并手动填充十六进制值(例如: -13 写成0xDA)。

首先将您的每个数字转换为十六进制。您可以在 Programmer 模式下(在 View 选项下)使用 Windows 计算器,在 dec 模式下输入小数,然后按 hex 以查看与十六进制格式相同的值。也许一些在线工具也可以做到这一点。

最终的十六进制值应该看起来像 78 DA 63 10 0C 33 29 8A 0C 32 51 49 31 C8 .... etc 直到结束的十六进制值 F0 等于你的结束小数点 -16.

那么你就可以轻松做到...

public string p()
{

    byte[] loc_Data = new byte[] {
    0x78, 0xDA, 0x63, 0x10, 0x0C, 0x33, 0x29, 0x8A, 
    0x0C, 0x32, 0x51, 0x49, 0x31, 0xC8, 0x0D, 0x30, etc etc ... until 0xF0
    };

    var loc_Uncompressed = Ionic.Zlib.ZlibStream.UncompressBuffer( loc_Data );
    return Encoding.UTF8.GetString( loc_Uncompressed ); //or try: loc_Uncompressed.ToArray()

}