【问题标题】:C# Encoding.UTF8 messing up the bytes[]C# Encoding.UTF8 弄乱了字节[]
【发布时间】:2012-04-23 10:09:32
【问题描述】:

我遇到了一个非常奇怪的问题,其中我有 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 

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

谢谢,

--

希拉兹

【问题讨论】:

    标签: c# utf-8 character-encoding


    【解决方案1】:

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

    可以偷偷地插入它们,然后将它们取出数据被输入到像Encoding.GetString 这样的 UTF-8 感知代码之前,但这不是一个好方法这个想法正是因为它是偷偷摸摸的(方式让不知道那里发生什么巫术的人感到困惑,因此非常适得其反)。

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

    【讨论】:

    • +1 如果您需要这样的标记,那么您可以在 Unicode 中的某处选择一个字符来代替使用,例如在私有范围之一中,然后使用这些字符的有效 UTF-8 编码作为标记。但是它们每个将超过一个字节。或者提前在标记周围截断字节流,然后一次将每个有效部分转换为 Unicode,但您需要小心不要使用这些字节实际获取真正的 UTF-8 编码 - 即您会有效地正在编写自己的解码器。
    【解决方案2】:

    数据只是标记之间的 UTF-8 ,所以如果是我,我会首先提取分隔部分,然后 UTF-8 解码每个部分分别读取 byte[] 以查找 binary 数据中的标记,为您提供 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);
        // ...
    }
    

    【讨论】:

    • 谢谢...我必须手动完成,因为要求将所有内容都以 UTF-8 编码,因为我的数据库仅为 UTF-8。我现在没有将任何内容转换为字符串,而是仅处理字节。
    • @SJunejo k,但请注意:您当前的策略不是 UTF-8。您的数据库完全有权向您爆炸。​​
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-10-07
    • 2014-03-04
    • 2020-01-16
    • 1970-01-01
    • 2021-11-22
    相关资源
    最近更新 更多