【问题标题】:Get string from UTF8 (Invalid URI: There is an invalid sequence in the string)从 UTF8 获取字符串(无效的 URI:字符串中存在无效序列)
【发布时间】:2014-07-24 07:57:26
【问题描述】:

你能帮我理解为什么下面代码的第二行会抛出异常吗?

string line1 = Uri.UnescapeDataString("Disk:%2FFolder");
string line2 = Uri.UnescapeDataString("Disk:%C0%AFFolder");

也许还有其他功能可以成功解码“磁盘:%C0%AFFolder”?

【问题讨论】:

  • 仅供参考:这与 UTF-8 完全无关
  • "%c0%af" 是“/”的非法 Unicode 表示。 source
  • %2F 和 %C0%AF 都使用 UTF-8 表示“/”,对吧?

标签: c# utf-8


【解决方案1】:

URLS ares 7bits ASCII。 W3schools 说:

只能使用 ASCII character-set 通过 Internet 发送 URL。

%C0 和 %AF 不是 8 位编码的。这就是为什么它没有被Uri.UnescapeDataString 解码。

【讨论】:

  • 谢谢。如何从“磁盘:%C0%AFFolder”获取字符串?
【解决方案2】:

我花了很多时间试图找到我的问题的答案。 最后我放弃了,决定自己写解码器。

原来如此。如果您想解码 UTF-8 字节(可能包含超长序列),请考虑使用以下代码:

    private static string GetString(byte[] bytes)
    {
        StringBuilder builder = new StringBuilder();
        int index = 0;

        while (index < bytes.Length)
        {
            if ((bytes[index] & 0x7F) == bytes[index])
            {
                Int32 code = bytes[index];
                byte[] codeBytes = BitConverter.GetBytes(code);
                builder.Append(UnicodeEncoding.UTF32.GetString(codeBytes));
                index += 1;
            }
            else if (((bytes[index] & 0xDF) == bytes[index]) && (index + 1) < bytes.Length
                                                             && ((bytes[index + 1] & 0xBF) == bytes[index + 1]))
            {
                Int32 code = ((bytes[index + 0] & 0x1F) << 06) +
                             ((bytes[index + 1] & 0x7F) << 00);
                byte[] codeBytes = BitConverter.GetBytes(code);
                builder.Append(UnicodeEncoding.UTF32.GetString(codeBytes));
                index += 2;
            }
            else if (((bytes[index] & 0xEF) == bytes[index]) && (index + 2) < bytes.Length
                                                             && ((bytes[index + 1] & 0xBF) == bytes[index + 1])
                                                             && ((bytes[index + 2] & 0xBF) == bytes[index + 2]))
            {
                Int32 code = ((bytes[index + 0] & 0x0F) << 12) +
                             ((bytes[index + 1] & 0x7F) << 06) +
                             ((bytes[index + 2] & 0x7F) << 00);
                byte[] codeBytes = BitConverter.GetBytes(code);
                builder.Append(UnicodeEncoding.UTF32.GetString(codeBytes));
                index += 3;
            }
            else if (((bytes[index] & 0xF7) == bytes[index]) && (index + 3) < bytes.Length
                                                             && ((bytes[index + 1] & 0xBF) == bytes[index + 1])
                                                             && ((bytes[index + 2] & 0xBF) == bytes[index + 2])
                                                             && ((bytes[index + 3] & 0xBF) == bytes[index + 3]))
            {
                Int32 code = ((bytes[index + 0] & 0x07) << 18) +
                             ((bytes[index + 1] & 0x7F) << 12) +
                             ((bytes[index + 2] & 0x7F) << 06) +
                             ((bytes[index + 3] & 0x7F) << 00);
                byte[] codeBytes = BitConverter.GetBytes(code);
                builder.Append(UnicodeEncoding.UTF32.GetString(codeBytes));
                index += 4;
            }
            else if (((bytes[index] & 0xFB) == bytes[index]) && (index + 4) < bytes.Length
                                                             && ((bytes[index + 1] & 0xBF) == bytes[index + 1])
                                                             && ((bytes[index + 2] & 0xBF) == bytes[index + 2])
                                                             && ((bytes[index + 3] & 0xBF) == bytes[index + 3])
                                                             && ((bytes[index + 4] & 0xBF) == bytes[index + 4]))
            {
                Int32 code = ((bytes[index + 0] & 0x03) << 24) +
                             ((bytes[index + 1] & 0x7F) << 18) +
                             ((bytes[index + 2] & 0x7F) << 12) +
                             ((bytes[index + 3] & 0x7F) << 06) +
                             ((bytes[index + 4] & 0x7F) << 00);
                byte[] codeBytes = BitConverter.GetBytes(code);
                builder.Append(UnicodeEncoding.UTF32.GetString(codeBytes));
                index += 5;
            }
            else if (((bytes[index] & 0xFD) == bytes[index]) && (index + 5) < bytes.Length
                                                             && ((bytes[index + 1] & 0xBF) == bytes[index + 1])
                                                             && ((bytes[index + 2] & 0xBF) == bytes[index + 2])
                                                             && ((bytes[index + 3] & 0xBF) == bytes[index + 3])
                                                             && ((bytes[index + 4] & 0xBF) == bytes[index + 4])
                                                             && ((bytes[index + 5] & 0xBF) == bytes[index + 5]))
            {
                Int32 code = ((bytes[index + 0] & 0x01) << 30) +
                             ((bytes[index + 1] & 0x7F) << 24) +
                             ((bytes[index + 2] & 0x7F) << 18) +
                             ((bytes[index + 3] & 0x7F) << 12) +
                             ((bytes[index + 4] & 0x7F) << 06) +
                             ((bytes[index + 5] & 0x7F) << 00);
                byte[] codeBytes = BitConverter.GetBytes(code);
                builder.Append(UnicodeEncoding.UTF32.GetString(codeBytes));
                index += 6;
            }
            else
                throw new Exception("Wrong UTF-8 format");
        }

        return builder.ToString();
    }

    public static void Main()
    {
        string source = "Disk:%FC%80%80%80%80%AFFolder";
        byte[] bytes = HttpUtility.UrlDecodeToBytes(source);
        string result = GetString(bytes);
    }

【讨论】:

    猜你喜欢
    • 2011-06-13
    • 2010-11-21
    • 1970-01-01
    • 1970-01-01
    • 2017-02-02
    • 2021-02-06
    • 2019-10-09
    • 1970-01-01
    • 2020-01-09
    相关资源
    最近更新 更多