You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何经UTF8解码再编码后的字节数组与原数组存在差异?

随机字节序列UTF8解码再编码后不一致的原因解析

问题场景

生成随机字节序列后,经UTF-8解码再编码,结果与原序列不一致,示例如下:

生成随机字节的PowerShell代码

[byte[]]$key = [byte[]]::new(32)
[System.Security.Cryptography.RandomNumberGenerator]::Create().GetBytes($key)
$key

输出:

15
173
198
89
162
161
144
104
125
86
154
204
166
238
193
40
51
58
167
0
150
118
37
203
198
161
64
229
101
25
176
201

解码再编码的PowerShell代码

$decoded = [System.Text.Encoding]::UTF8.GetString($key)
$encoded = [System.Text.Encoding]::UTF8.GetBytes($decoded)
$encoded

输出:

15
239
191
189
239
191
189
89
239
191
189
239
191
189
239
191
189
104
125
86
239
191
189
204
166
239
191
189
239
191
189
40
51
58
239
191
189
0
239
191
189
118
37
239
191
189
198
161
64
239
191
189
101
25
239
191
189
239
191
189

可见解码再编码后的字节序列已被修改,但使用[System.Text.Encoding]::Unicode...时流程可正常运行。


原因解析

1. UTF-8的编码规则限制

UTF-8是有结构的变长编码,并非所有字节组合都符合其规范:

  • 单字节字符范围为0x00-0x7F(对应ASCII字符);
  • 多字节字符需遵循固定格式:双字节字符以0xC0-0xDF开头,后续字节必须是0x80-0xBF;三字节字符以0xE0-0xEF开头,后续两个字节为0x80-0xBF,以此类推。
    随机生成的字节序列几乎必然包含不符合规则的内容(比如单独的0x80-0xFF字节、不完整的多字节片段),这些都是无效的UTF-8字节。

2. .NET UTF-8解码器的错误处理逻辑

当UTF8.GetString()遇到无效字节序列时,默认会用替换字符U+FFFD(显示为�)替代无效部分,该字符对应的UTF-8字节序列就是0xEF 0xBF 0xBD——也就是输出中反复出现的239 191 189。再次编码时,这些替换字符会被转换成对应字节,导致原序列被修改。

3. UTF-8与Unicode的关系误区

“UTF8支持所有Unicode字符”的说法是对的:UTF-8可以编码所有Unicode字符,但反过来不成立——不是任意字节序列都能解码为合法Unicode字符,只有符合UTF-8编码规则的字节序列才能正确解码,否则会触发错误处理。

4. UTF-16(Unicode编码)能正常工作的原因

.NET中的[System.Text.Encoding]::Unicode实际是UTF-16LE编码,其规则为:

  • 大部分字符用两个字节表示;
  • 辅助平面字符用四个字节(两个码元)表示。
    对于UTF-16来说,任何两个字节的组合都对应一个合法码元(即使该码元不对应有效Unicode字符,解码器也会原样保留),因此随机字节序列解码再编码后能完全还原。

内容的提问来源于stack exchange,提问作者AKozak

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 22:01:01