1 回答
TA贡献1735条经验 获得超5个赞
在原始编码字节中,有问题的字符代码是0x0093。
您遇到的问题是,在Default系统上的编码中(在 Windows 上将是系统当前的代码页),编码的字符0x0093无法识别。因此,当您尝试对其进行解码时,您将获得 UTF16 字符点0xfffd(这是 .NET 解码器针对无法识别的字符的默认值)。然后将其编码回默认编码0x93c2(您在输出中看到的字节序列,以十进制表示,194后跟147)。
无论如何,此行为与默认编码设置为 UTF8 一致,可能表明它是 Linux 系统(大多数 Windows 系统将使用某些特定于区域设置的代码页作为默认编码,而不是 UTF8)。
如果您希望将原始字节0x93转换为具有基本相同值(即0x0093,又名'\u0093')的 UTF16 字符,那么您需要使用文本编码来解码原始字节,其中代码点0x93实际上转换为 UTF16 代码点0x0093。
幸运的是,有一个网站实际上会告诉我们哪些编码包含该字符,以及它们的值是什么:https ://www.compart.com/en/unicode/charsets/containing/U+0093
从该表中,我们可以看到大量的编码都是这种情况(还有一些编码将 UTF16 字符'\u0093'编码为不同的值,即0x33……显然,我们不想要其中任何一个)。列表中的第一个编码 - “ISO-8859-1” - 看起来合适,所以让我们尝试使用它来解码你的字节:
byte[] bytes = new byte[] { 0x19, 0x93, 0x0d, 0x0a, 0x1a, 0x0a };
string s = "\u0019\u0093\r\n\u001a\n";
Encoding encoding = Encoding.GetEncoding("iso-8859-1");
System.Console.WriteLine(encoding.GetString(bytes) == s);
System.Console.WriteLine(s.Length);
foreach (var b in encoding.GetBytes(s))
{
System.Console.WriteLine("Byte: " + b);
}
System.Console.WriteLine(encoding.GetString(bytes) == s);
这输出正是你想要的:
True
6
Byte: 25
Byte: 147
Byte: 13
Byte: 10
Byte: 26
Byte: 10
True
显示的字节甚至是bytes数组中的确切字节,我们可以通过将此行添加到程序末尾来演示:
System.Console.WriteLine(encoding.GetBytes(s).SequenceEqual(bytes));
这也将打印True.
这个故事的寓意是:了解您尝试解码的字节的原始编码不是可选的。您必须确切地知道使用了哪种编码,因为它就是:一种编码。如果您使用了错误的编码,您可能还想尝试解码加密的数据。
根据定义,不同的文本编码是不同的。这意味着一种编码中的字节含义与其他编码中的字节含义完全不同(某种程度上……大多数编码在最低 128 个代码点中重叠,因为它们都基于 ASCII)。如果您使用错误的编码来解码某些字节,您只会得到随机结果(或者,在这种情况下,解码器将根本无法识别该字符并将其转换为表示无法识别的字符的占位符)。
- 1 回答
- 0 关注
- 90 浏览
添加回答
举报