如何解决C# MemoryStream无法写入带负号字节导致无法解压缩获取UTF字符串的问题?
解决C#写入带符号字节及ZLIB解压缩问题
我来帮你搞定这个问题!核心卡点其实是C#和ActionScript对字节的表示差异:ActionScript的writeByte用的是有符号字节(范围-128到127),而C#的byte类型是无符号的(0到255)。那些你以为的“负字节”,本质上就是AS3对大于127的无符号字节的另一种写法,只要转成C#对应的无符号值就能正常处理。
第一步:把AS3的负字节转成C#无符号字节
先把你AS3代码里的负字节转换成C#能识别的无符号值,转换规则很简单:无符号值 = 256 + 有符号值(因为有符号字节的-1对应无符号的255,以此类推)。对应关系如下:
-38→218-118→138-56→200-30→226-16→240
第二步:C#中解压缩并读取UTF字符串
AS3的ByteArray.uncompress()默认使用ZLIB压缩格式,所以C#里要用DeflateStream来解压缩(注意要跳过ZLIB的前两个头字节),再按照AS3readUTF()的规则读取字符串(先读16位大端长度,再读UTF-8字节)。
以下是完整的C#代码示例:
using System; using System.IO; using System.IO.Compression; using System.Text; class Program { static void Main() { // 对应AS3代码里的ByteArray内容,已转换为无符号字节 byte[] compressedBytes = new byte[] { 120, 218, 99, 16, 12, 51, 41, 138, 12, 50, 81, 73, 49, 200, 13, 48, 54, 54, 14, 48, 46, 2, 0, 45, 226, 4, 240 }; string resultString; using (var compressedMs = new MemoryStream(compressedBytes)) { // 跳过ZLIB的前两个头字节(CMF和FLG) compressedMs.Position = 2; using (var deflateStream = new DeflateStream(compressedMs, CompressionMode.Decompress)) using (var decompressedMs = new MemoryStream()) { // 解压缩到内存流 deflateStream.CopyTo(decompressedMs); decompressedMs.Position = 0; // 按照AS3 readUTF()的规则读取:先读16位大端长度,再读UTF-8字节 using (var reader = new BinaryReader(decompressedMs, Encoding.UTF8)) { // 读取长度(AS3用UTF-16大端存储) ushort strLength = reader.ReadUInt16(); // 读取对应长度的字节并转成字符串 resultString = Encoding.UTF8.GetString(reader.ReadBytes(strLength)); } } } Console.WriteLine("解压缩后的UTF字符串:"); Console.WriteLine(resultString); } }
关键细节说明
- 字节表示差异:C#里不存在“写负字节”的问题,因为负字节只是AS3对高位无符号字节的有符号表示,转换后直接写入
MemoryStream即可。 - ZLIB格式处理:AS3的
uncompress()默认用ZLIB,而C#的DeflateStream处理的是原始deflate数据,所以必须跳过ZLIB的前两个头字节(120和218)。 - UTF读取规则:AS3的
readUTF()不是直接读UTF-8,而是先读一个16位大端整数表示字符串的字节长度,再读取对应长度的UTF-8字节,C#里要严格遵循这个规则才能正确解析。
如果是你自己在C#中生成需要AS3解压缩的字节流,记得在压缩数据前加上ZLIB的头字节(120和218),这样AS3的uncompress()才能正常识别。
内容的提问来源于stack exchange,提问作者Wojtek Kozłowski
相关产品推荐
相关产品推荐

