C#Encoding.UTF8弄乱了字节[]

时间:2012-04-23 10:09:32

标签: c# utf-8 character-encoding

我面临着非常奇怪的问题,其中我有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 

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

谢谢,

-

Sheeraz

2 个答案:

答案 0 :(得分:7)

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

可以偷偷插入它们,然后在将数据提供给支持UTF-8的代码(例如Encoding.GetString)之前将它们带回,但这不是一个好主意,因为它是偷偷摸摸的(方式让那些不知道伏都教在那里发生什么的人感到困惑,因而非常适得其反)。

更合理的选择是在字符串中插入“特殊”UTF-8编码字符。这在技术上需要(特别是如果你选择一个编码为1个字节的字符,因为那些字符也更有可能发生在你的实际有效载荷中)你还想出了一个转义这些字符的方案当它们在你的有效载荷内自然发生时。

答案 1 :(得分: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);
    // ...
}