您能否帮我理解为什么以下代码中的第二行会引发异常?
string line1 = Uri.UnescapeDataString("Disk:%2FFolder");
string line2 = Uri.UnescapeDataString("Disk:%C0%AFFolder");
也许有一些其他功能能够成功解码“Disk:%C0%AFFolder”?
答案 0 :(得分:3)
URLS ares 7bits ASCII。 W3schools说:
网址只能通过互联网使用ASCII character-set发送。
%C0和%AF不是8位编码的。这就是Uri.UnescapeDataString
未解码的原因。
答案 1 :(得分:0)
我花了很多时间试图找到问题的答案。 最后我放弃了,决定自己编写解码器。
就是这样。如果要解码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);
}