【问题标题】:Why is the console not printing the characters i am expecting为什么控制台不打印我期望的字符
【发布时间】:2016-02-02 01:54:24
【问题描述】:

我目前正在尝试让自己了解不同的编码类型。我尝试制作一个简单的控制台应用程序来告诉我类型之间的区别。

byte[] byteArray = new byte[] { 125, 126, 127, 128, 129, 130, 250, 254, 255 };
string s = Encoding.Default.GetString(byteArray);
Console.OutputEncoding = Encoding.Default;
Console.WriteLine("Default: " + s);

s = Encoding.ASCII.GetString(byteArray);
Console.OutputEncoding = Encoding.ASCII;
Console.WriteLine("ASCII: " + s);

s = Encoding.UTF8.GetString(byteArray);
Console.OutputEncoding = Encoding.UTF8;
Console.WriteLine("UTF8: " + s);

但是输出与我预期的完全不同。

Default: }~€‚úûüýþÿ
ASCII: }~?????????
UTF8: }~���������

嗯...字符从控制台输出复制到这里也不是很好,所以这里是一个打印屏幕。

我希望看到扩展的 ASCII 字符。默认编码几乎是正确的,但它无法显示251, 252 and 253,但这可能是 Console.writeLine() 的一个缺点,尽管我不希望这样。

调试时变量的表示如下:

Default encoded string = "}~€‚úûüýþÿ"
ASCII encoded string = "}~?????????"
UTF8 encoded string = "}~���������"

谁能告诉我我做错了什么?我希望其中一种编码类型能够正确显示扩展的 ASCII 表,但显然没有一种可以......

一点上下文:
我正在尝试确定哪种编码最适合我们公司的标准,我个人认为 UTF8 可以,但我的主管希望在我们决定之前先看看一些示例。

显然我们知道我们需要时不时地使用其他编码类型(例如串行通信使用 7 位,因此我们不能在那里使用 UTF8),但通常我们希望坚持使用一种编码类型。目前我们随机使用默认、ASCII 和 UTF8,所以这不是一件好事。

编辑
输出根据:

Console.WriteLine("Default: {0} for {1}", s, Console.OutputEncoding.CodePage);

编辑 2:
因为我认为可能没有一种编码,其中扩展的 ascii 字符对应于我链接到的表中的十进制数字,所以我把它转过来了:

char specialChar = '√';
int charNumber = (int)specialChar;

给我数字:8730,在表格中是 251

【问题讨论】:

  • 你的控制台的代码页是什么?查看“属性”对话框。请注意,没有一种称为“扩展 ASCII”的编码 - 有许多 不同 8 位编码共享前 128 个值的 ASCII。 (是的,UTF-8 几乎可以肯定是标准化的最佳选择。)
  • 顺便说一句,您应该在这里分离两个问题:a)您可以在控制台上打印哪些字符; b)您的字符串中有哪些字符。您可以确定后者没有前者...有关示例代码,请参阅csharpindepth.com/Articles/General/Strings.aspx
  • @JonSkeet 好问题,我认为Console.OutputEncoding = Encoding.ASCII; 会给我正确的代码页。
  • 不,这会改变您将字节转换为字符串的方式 - 它不会影响控制台能够显示的内容。
  • 您单击左上角,然后选择“属性”——这就是我说要查看“属性”对话框的原因。另见stackoverflow.com/questions/388490

标签: c# utf-8 character-encoding ascii


【解决方案1】:

在您的情况下,输出编码应该几乎无关紧要,因为您甚至没有使用 Unicode。此外,您需要将控制台窗口设置从 Raster 字体更改为 TrueType 字体,例如 Lucida Console 或 Consolas。当控制台设置为光栅字体时,您只能使用 OEM 编码(在您的情况下为 CP850),这意味着 Unicode 根本不起作用。

但是,所有这些也都没有实际意义,因为您的代码……充其量是奇怪的。首先,关于这里发生的事情:您有一个字节数组,以各种编码解释它并返回一个(Unicode)字符串。将该字符串写入控制台时,Unicode 字符将转换为控制台代码页中最接近的等效字符(此处为 850)。如果没有等价的,甚至没有接近,那么你会得到一个问号?。这在 ASCII 和 127 以上的字符中最为显着,因为它们根本不存在于 ASCII 中。

如果你想看到你想看到的字符,那么要么在整个过程中使用正确的编码,而不是试图插手,直到它有点工作,或者只是使用正确的字符开始。

Console.WriteLine("√ⁿ²")

应该确实可以工作,因为它贯穿了上述编码翻译过程。

【讨论】:

  • Console.OutputEncoding = Encoding.Default; 和字体类型设置为 lucida 控制台时,我确实得到了正确的输出。我链接到的扩展 ascii 表的字节值不适用于 utf-8,utf-8 对扩展 ascii 有不同的数字。所以我可以完美地以 utf-8 格式保存任何东西我只需要小心不要将 254 字节值传递给 utf-8 编码并期望扩展 ascii。
【解决方案2】:

奇怪,这段代码

Console.OutputEncoding = Encoding.Default;
Console.WriteLine("Default: {0} for {1}", s, Console.OutputEncoding.HeaderName);
s = Encoding.ASCII.GetString(byteArray);
Console.OutputEncoding = Encoding.ASCII;
Console.WriteLine("ASCII: {0} for {1}", s, Console.OutputEncoding.HeaderName);
s = Encoding.UTF8.GetString(byteArray);
Console.OutputEncoding = Encoding.UTF8;
Console.WriteLine("UTF8: {0} for {1}", s, Console.OutputEncoding.HeaderName);

我得到了这个:

Default: }~€‚úþÿ for Windows-1252
ASCII: }~?????? for us-ascii
UTF8: }~ ������ for utf-8

这是我所期望的。默认代码页是 CP1252,而不是表格显示的 CP850。 为您的控制台尝试另一种默认字体,例如“Consolas”或“Lucidia Console”并检查输出。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-11-22
    • 1970-01-01
    • 2012-11-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-15
    • 2020-06-05
    • 2021-07-08
    相关资源
    最近更新 更多