2012-04-23 100 views
3

我面临着非常奇怪的问题,其中我有byte [],当我传递给Convert.UTF8.GetString(byte [] bytes)方法时,系统编码是搞乱了我的字节,只用几个特殊的字节(我在系统中用作标记)替换为三个char字符串表示形式。C#Encoding.UTF8弄乱了字节[]

[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(字节)的方法我得到以下输出;

​​

实际值不应该有' ',因为这意味着它没有编码并用' '代替这些特殊字节。无论如何,我可以解决这个问题,即转换为字符串并将特殊字节表示保留为单个字符。

我有以下特殊字节,我试图用作标记;

byte AM = (byte) 254 
byte VM = (byte) 253 
byte SM = (byte) 252 

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

感谢,

-

Sheeraz

回答

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); 
    // ... 
} 
+0

谢谢...我必须手动完成它,因为要求是将UTF-8编码的所有内容都编码为我的数据库仅为UTF-8。我现在我没有将任何东西转换成字符串,但只处理字节。 – SJunejo 2012-04-24 22:27:47

+0

@SJunejo k,但请注意:您目前的策略**不是UTF-8 **。您的数据库将完全处于您的权利爆炸范围之内。 – 2012-04-24 22:30:24

7

不能使用这些特殊值作为一个UTF-8字符串中的标记,因为字符串结束根据UTF-8 encoding rules是无效。

可以偷偷插入他们,然后带他们回来了之前的数据被送到UTF-8数据的相关代码一样Encoding.GetString,但因为它是偷偷摸摸不是一个好主意,正好混乱到(方式任何人都不知道在那里发生了什么伏都教,因此非常不利于生产)。

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

+0

+1如果您需要这样的标记,那么您可以在Unicode内的某处选择一个字符来代替,例如,在其中一个专用范围内,然后使用这些字符的有效UTF-8编码作为标记。但是它们每个都会超过一个字节。或者提前在您的标记周围切掉字节流,然后将每个有效部分转换为Unicode,但是您需要小心,不要真正使用这些字节来获取真正的UTF-8编码 - 即,您会有效地正在编写你自己的解码器。 – Rup 2012-04-23 10:13:21