3

我面临一个非常奇怪的问题,其中我有 byte[] 并且当我将它传递给 Convert.UTF8.GetString(byte[] bytes) 方法时,系统编码弄乱了我的字节并且只替换了几个特殊字节(我在我的系统中用作标记)到一些三个字符字符串表示。

[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 

您的帮助和意见将不胜感激。

谢谢,

--

希拉兹

4

2 回答 2

7

您不能将这些特殊值用作 UTF-8 字符串中的标记,因为根据 UTF-8编码规则,该字符串最终无效。

可以偷偷地插入它们,然后将数据馈送到可识别 UTF-8 的代码如在那里,因此非常适得其反)。Encoding.GetString

更明智的选择是在字符串中简单地插入“特殊”UTF-8 编码字符。这在技术上需要(特别是如果您选择一个编码为 1 字节的字符,因为这些字符也更有可能出现在您的实际有效负载中)您还想出一个方案来在这些字符自然出现在您的有效负载中时对其进行转义.

于 2012-04-23T10:11:39.747 回答
2

标记之间的数据只是 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);
    // ...
}
于 2012-04-23T10:29:57.530 回答