C# 将扩展ASCII字符转换为it';使用Console.ReadKey()方法和ConsoleKeyInfo变量创建正确的演示文稿
阅读了大约30分钟,并没有在这个网站上找到一些具体的内容 假设在C#中的控制台应用程序中出现以下情况:C# 将扩展ASCII字符转换为it';使用Console.ReadKey()方法和ConsoleKeyInfo变量创建正确的演示文稿,c#,encoding,console,ascii,decoding,C#,Encoding,Console,Ascii,Decoding,阅读了大约30分钟,并没有在这个网站上找到一些具体的内容 假设在C#中的控制台应用程序中出现以下情况: ConsoleKeyInfo cki; cki = Console.ReadKey(true); Console.WriteLine(cki.KeyChar.ToString()); //Or Console.WriteLine(cki.KeyChar) as well Console.ReadKey(true); 现在,让我们将?放在控制台条目中,并通过控制台将其分配到cki。ReadKe
ConsoleKeyInfo cki;
cki = Console.ReadKey(true);
Console.WriteLine(cki.KeyChar.ToString()); //Or Console.WriteLine(cki.KeyChar) as well
Console.ReadKey(true);
现在,让我们将?
放在控制台条目中,并通过控制台将其分配到cki
。ReadKey(true)
。将显示的不是?
符号,而是显示的符号。许多其他角色也是如此。示例:ñ
显示·,
显示-
,'
显示
现在,让我们使用相同的代码snipplet,并为更类似于Console.ReadLine()的行为添加一些内容:
string data = string.Empty;
ConsoleKeyInfo cki;
for (int i = 0; i < 10; i++)
{
cki = Console.ReadKey(true);
data += cki.KeyChar;
}
Console.WriteLine(data);
Console.ReadKey(true);
所以,现在这个问题有了更广泛的焦点。。。哪些其他函数只需按下一个键即可完成其执行,并返回按下的内容(ReadKey()的替代项)?我认为没有这样的替代品,但是一个确定的答案是有用的。问题不在于控制台不知道如何处理Unicode(它知道,而且正确地说)。问题在于您对键盘上按键的理解、按键代码的转换、按键代码的字符转换以及ReadKey()方法的工作原理
首先:如果您想读取连续字符,请使用Console.ReadLine()
,它可以为您完成所有运算,而且效果更好。
让我们看一下下面的节目:
Console.WriteLine("Press a key to start (Enter to stop).");
var key = Console.ReadKey();
var allKeys = "";
while(key.Key != ConsoleKey.Enter)
{
Console.WriteLine(key.KeyChar);
allKeys += key.KeyChar;
key = Console.ReadKey();
}
它从输入中读取一个键,然后将其附加到字符串中。没什么好担心的,对吧?错了!在美国国际键盘上,您可以执行以下操作:
- 类型“+a”变为
a
- 键入Alt+123将变成
{
- 键入Alt+3355将变为←李>
- 输入;就像在西班牙语键盘上一样,变为ñ
根据键盘的不同,您会为某个字符按不同的键。有时您会按多个键的组合。上面的第一个组合被记录为\0a
字符串,keycode0
(不在枚举中),然后是ConsoleKey.a
。生成的总字符串现在是“\0”{←ñ“
Alt+123/3355被记录为键码18(这是Alt键)。在将数字键发送到控制台之前,操作系统将数字键转换为字符
在美国键盘上键入;
或在西班牙语键盘上键入ñ
将显示ConsoleKey.Oem1
(美国)和ConsoleKey.Oem3
(西班牙语)
虽然我无法模仿您的行为,但这可能是因为我没有您的屏幕,但您作为控制台字体使用的字体似乎不支持非Unicode字符。在Windows 7上,默认情况下不支持非Unicode字符,我不知道其他Windows版本是否支持。也可能是控制台的代码页设置不正确
总结
字符的组成取决于键盘布局、国际设置中选定的键盘、选定的语言、控制台中选定的代码页,以及是否允许组合键(IME会让情况变得更糟!)。从KeyChar转到普通字符通常很简单,但这取决于系统设置是否相互同步
当我在我的系统上运行您的示例时,我没有相同的行为。但是,我没有您的系统
从一个关键点到一个角色是一件棘手的事情。我建议你不要依靠自己的能力来重新创造系统中已经存在的东西。尝试了解发生了什么是一种好的做法,但实际上,回到ReadLine
;)
编辑:
我刚刚看到了您的最新编辑。请注意,您可以对输入和输出使用不同的编码(Console.InputEncoding
和Console.OutputEncoding
)。我还想引用另一个线程来强调,当您切换到Unicode时,代码页不再重要。这是最新Windows版本的默认行为:
如果选择Unicode字体,如Lucida Console或ConsoleAs,则
您将能够在控制台上查看和键入Unicode字符,
不管chcp怎么说:
ReadLine()重新配置代码页以正确使用扩展的ASCII和Unicode字符。ReadKey()将其保留为EN-US默认值(代码页850)
只需使用打印所需字符的代码页即可,仅此而已。有关其中一些字符,请参阅:)
因此,对于按下键
,解决方案如下:
Console.OutputEncoding = Encoding.GetEncoding(1252); //Also 28591 is valid for `Ñ` key, and others too
string data = string.Empty;
ConsoleKeyInfo cki;
cki = Console.ReadKey(true);
data += cki.KeyChar;
Console.WriteLine(data);
Console.ReadKey(true);
简单:)
还有一个附带说明:在某些情况下,还需要重新配置控制台.inpunecoding
属性
另外,请注意,如果您为控制台选择另一种字体(Lucida console/ConsoleAs),这个问题仍然会发生。感谢用户Abel,Lota为此指定了字体更改解决方案,并让我自己发现这是false
Mmm…好吧,从这里,我想到了一个问题…为什么console.ReadLine()方法?它确实得到了正确的字符,比如ñ、?、并以正确的方式将其存储到字符串或字符中。如果Microsoft只发布其方法的源代码,事情会变得更容易:DWell,他们做到了。关于控制台不支持Unicode,我不相信……两个快速结果正好相反:好吧,是r阅读源代码,发现了两个有趣的差异。Console.ReadKey()使用buffer.keyEvent.uChar
返回控制台中引入的字符。buffer来自Win32Native.InputRecord
,它是一种变量类型(没有Win32Native.InputRecord的源可用,完全正确),然后keyEvent
和uChar
将为程序员带来未知:S。情况是缓冲区不能以正确的方式处理扩展的ASCII/Unicode。对于ReadLine()
Console.OutputEncoding = Encoding.GetEncoding(1252); //Also 28591 is valid for `Ñ` key, and others too
string data = string.Empty;
ConsoleKeyInfo cki;
cki = Console.ReadKey(true);
data += cki.KeyChar;
Console.WriteLine(data);
Console.ReadKey(true);