You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在C#中解码%x##格式的RFC 3986编码字符串?

在C#中解码%xXX格式的RFC 3986编码字符串

这个问题我之前也踩过坑!内置的Uri、HttpUtility或WebUtility类只认标准的%XX格式编码,碰到%xXX这种带x前缀的就无法正确解码了。不过有两种简单的解决方案,推荐优先用第一种,省心又靠谱:

方法一:转换格式后用内置解码方法

核心思路是先把非标准的%xXX格式替换成标准的%XX格式,再调用内置方法解码。这里用正则表达式来做替换最方便:

using System.Text.RegularExpressions;

// 示例编码字符串
string encodedStr = "Hello%x20World%x21%xE6%x9D%x8E";
// 替换%xXX为%XX
string standardEncoded = Regex.Replace(encodedStr, @"%x([0-9A-Fa-f]{2})", "%$1");
// 使用Uri.UnescapeDataString解码(也可以用WebUtility.UrlDecode,注意两者在某些字符上的差异)
string decodedStr = Uri.UnescapeDataString(standardEncoded);

Console.WriteLine(decodedStr); // 输出: Hello World!李

为什么推荐这种方法?

内置的解码方法已经处理了各种边缘情况,比如UTF-8多字节字符的解码(像上面示例中的中文“李”),不用自己手动处理编码逻辑,避免出错。

方法二:手动实现解码逻辑

如果你不想依赖正则或内置方法,也可以手动遍历字符串处理:

string encodedStr = "Hello%x20World%x21";
List<char> decodedChars = new List<char>();
int index = 0;

while (index < encodedStr.Length)
{
    // 检查当前位置是否是%x开头,且后面有足够的字符
    if (index + 3 < encodedStr.Length && encodedStr[index] == '%' && encodedStr[index + 1] == 'x')
    {
        // 提取后面两位十六进制字符
        string hexPart = encodedStr.Substring(index + 2, 2);
        // 尝试转换为字节
        if (byte.TryParse(hexPart, System.Globalization.NumberStyles.HexNumber, null, out byte charByte))
        {
            decodedChars.Add((char)charByte);
            index += 4; // 跳过%xXX四个字符
            continue;
        }
    }
    // 不是有效编码,直接添加原字符
    decodedChars.Add(encodedStr[index]);
    index++;
}

string decodedStr = new string(decodedChars.ToArray());
Console.WriteLine(decodedStr); // 输出: Hello World!

这种方法适合需要高度自定义解码逻辑的场景,但要注意如果是UTF-8多字节字符,还需要额外处理字节拼接的逻辑,所以一般情况下优先用方法一。

内容的提问来源于stack exchange,提问作者Matteo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.06 09:14:08