C# Encoding.UTF8 弄乱了字节[]
本文关键字:字节 乱了 Encoding UTF8 | 更新日期: 2023-09-27 18:31:55
我遇到了一个非常奇怪的问题,其中我有byte[],当我将其传递给Convert.UTF8.GetString(byte[]字节)方法时,系统编码弄乱了我的字节,并且只将几个特殊字节(我在系统中用作标记)替换为大约三个字符字符串表示。
[0] 70 byte
[1] 49 byte
[2] 45 byte
[3] 86 byte
[4] 49 byte
[5] 253 byte <-- Special byte
[6] 70 byte
[7] 49 byte
[8] 45 byte
[9] 86 byte
[10]50 byte
[11]253 byte <-- Special byte
[12]70 byte
[13]49 byte
[14]45 byte
[15]86 byte
[16]51 byte
当我将上面的 byte[] 传递到 Encoding.UTF8.GetString(bytes) 方法时,我得到以下输出;
private Encoding _encoding = System.Text.Encoding.GetEncoding("UTF-8", new EncoderReplacementFallback("?"), new DecoderReplacementFallback("?"));
_encoding.GetString(bytes) "F1-V1�F1-V2�F1-V3" string
实际值不应具有",因为这意味着它无法编码并将这些特殊字节替换为"。无论如何,我可以解决这个问题,即转换为字符串并将特殊字节表示形式保留为单个字符。
我有以下特殊字节,我试图将其用作标记;
byte AM = (byte) 254
byte VM = (byte) 253
byte SM = (byte) 252
您的帮助和意见将不胜感激。
谢谢
--
希拉兹
不能将这些特殊值用作 UTF-8 字符串中的标记,因为根据 UTF-8 编码规则,字符串最终无效。
您可以偷偷插入它们,然后在数据被馈送到 UTF-8 感知代码(如 Encoding.GetString
)之前将它们取出,但这不是一个好主意,因为它很偷偷摸摸(对于任何还不知道那里发生了什么巫毒教的人来说都是令人困惑的,因此非常适得其反)。
一个更明智的选择是简单地在字符串中插入"特殊"UTF-8 编码字符。这在技术上需要(特别是如果您选择一个编码为 1 字节的字符,因为这些字符也更有可能出现在您的实际有效负载中)您还需要想出一种方案来转义这些字符,当它们自然出现在您的有效负载中时。
数据在标记之间只有 UTF-8,所以如果是我,我会先提取分隔部分,然后 UTF-8 分别解码每个部分,即通读byte[]
寻找二进制数据中的标记,给你 3 个二进制块(70,49,45,86,49; 70,49,45,86,50; 70,59,45,86,51),然后解码为 3 个字符串。您无法对整个二进制序列进行 UTF-8 解码,因为它不是有效的 UTF-8。
个人而言,我会说在这里使用分隔符是危险的;我可能会选择长度前缀方法,以便
- 我知道我没有意外地将分隔符和真实数据混为一谈
- 我可以比逐字节更有效地处理它
例如,如果我们使用"varint"长度前缀,那就是:
05,70,49,45,86,49,05,70,49,45,86,50,05,70,59,45,86,51
其中05
是"varint"长度,我们将其解释为5个字节;这意味着我们可以很好地处理:
// pseude code
while(!EOF) {
int len = ReadVarint();
var blob = ReadBytes(len);
string s = Utf8Decode(blob);
// ...
}