Encoding.GetEncoding(437).GetString() bug?

本文关键字:bug GetString GetEncoding Encoding | 更新日期: 2023-09-27 18:04:44

我有以下测试程序

char c = '§';
Debug.WriteLine("c: " + (int)c);
byte b = Encoding.GetEncoding(437).GetBytes("§")[0];
Debug.WriteLine("b: " + b);
char c1 = Encoding.GetEncoding(437).GetString(new byte[] { 21 })[0];
Debug.WriteLine("c1: " + (int)c1);

生成如下结果:

c: 167
b: 21
c1: 21

正如我在这里看到的GetBytes工作正常
167 in unicode => 21 in CP437
但是GetString不起作用
21 in CP437 => 21 in unicode

这是一个bug还是我的错误?

Encoding.GetEncoding(437).GetString() bug?

CP437对于0-31范围内的字符不是"双向"的。如您所链接的维基百科页面所述:

在很多情况下,0 ~ 31的代码和127的代码都可以不会产生这些符号。其中一些(或全部)将被解释作为ASCII控制字符。

将Unicode字符映射到该范围内受支持的CP437字符可以工作,但反之则不行。例如,以字节13和字节10表示的字符为例:如果您将它们放在CP437字符串中,则很可能希望保留回车和换行字符,而不是将其转换为子弹和音符。

.net支持两种不同的字符,这两种字符(通常)都呈现为§:

char c1 = (char)21;
char c2 = (char)167;
Console.WriteLine(c1 == c2);  // prints false
Console.WriteLine(c1);        // prints §
Console.WriteLine(c2);        // prints §

字符21是一个特殊的控制字符,在文本模式下输出时显示为§

CP437允许21被解释为控制字符或文字§。显然,GetString选择将其解释为控制字符(这是一个完全有效的选项),因此,将其映射到Unicode控制字符21而不是Unicode文字§