简体   繁体   English

使用Console.ReadKey()方法和ConsoleKeyInfo变量将扩展的ASCII字符转换为正确的表示形式

[英]Convert extended ASCII characters to it's right presentation using Console.ReadKey() method and ConsoleKeyInfo variable

Readed about 30 minutes, and didn't found some specific for this in this site. 阅读了大约30分钟,并且在此站点中未找到与此相关的特定内容。

Suppose the following, in C#, console application: 假设在C#中,以下控制台应用程序:

ConsoleKeyInfo cki;
cki = Console.ReadKey(true);
Console.WriteLine(cki.KeyChar.ToString()); //Or Console.WriteLine(cki.KeyChar) as well
Console.ReadKey(true);

Now, let's put ¿ in the console entry, and asign it to cki via a Console.ReadKey(true) . 现在,让我们把¿在控制台的条目,ASIGN它cki通过Console.ReadKey(true) What will be shown isn't the ¿ symbol, the ¨ symbol is the one that's shown instead. 将显示的不是¿符号,而是¨符号。 And the same happens with many other characters. 其他许多角色也是如此。 Examples: ñ shows ¤ , ¡ shows - , ´ shows ï . 例如: ñ显示¤¡显示-´显示ï

Now, let's take the same code snipplet and add some things for a more Console.ReadLine() like behavior: 现在,让我们采用相同的代码片段,并为一些类似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);

The question, how to handle this by the right way, end printing the right characters that should be stored on data , not things like ¨ , ¤ , - , ï , etc? 问题是,如何以正确的方式处理此问题,结束打印应存储在data上的正确字符,而不是打印诸如¨¤-ï等之类的字符?

Please note that I want a solution that works with ConsoleKeyInfo and Console.ReadKey() , not use other variable types, or read methods. 请注意,我想要一个与ConsoleKeyInfoConsole.ReadKey()使用的解决方案,而不使用其他变量类型或读取方法。

EDIT: 编辑:

Because ReadKey() method, that comes from Console namespace, depends on Kernel32.dll and it definetively bad handles the extended ASCII and unicode, it's not an option anymore to just find a valid conversion for what it returns. 因为来自Console命名空间的ReadKey()方法依赖于Kernel32.dll,并且在定义上无法正确处理扩展的ASCII和unicode,所以不再只能为返回的内容查找有效的转换了。

The only valid way to handle the bad behavior of ReadKey() is to use the cki.Key property that's written in cki = Console.ReadKey(true) execution and apply a switch to it, then, return the right values on dependence of what key was pressed. 处理ReadKey()不良行为的唯一有效方法是使用在cki cki = Console.ReadKey(true)执行中编写的cki.Key属性,并对其执行一个开关,然后根据所依赖的内容返回正确的值按键。

For example, to handle the Ñ key pressing: 例如,要处理Ñ键,请按以下步骤:

string data = string.Empty;
ConsoleKeyInfo cki;
cki = Console.ReadKey(true);
switch (cki.Key)
{
    case ConsoleKey.Oem3:
        if (cki.Modifiers.ToString().Contains("Shift")) //Could added handlers for Alt and Control, but not putted in here to keep the code small and simple
            data += "Ñ";
        else
            data += "ñ";
        break;
}
Console.WriteLine(data);
Console.ReadKey(true);

So, now the question has a wider focus... Which others functions completes it's execution with only one key pressed, and returns what's pressed (a substitute of ReadKey())? 因此,现在这个问题得到了更广泛的关注...哪些其他功能仅需按一个键即可完成其执行,并返回所按的内容(替代ReadKey())? I think that there's not such substitutes, but a confirmed answer would be usefull. 我认为没有这样的替代品,但是肯定的答案将是有用的。

The problem is not that the Console doesn't know how to deal with Unicode (it does, and correctly, check out this thread ). 问题不在于控制台不知道如何处理Unicode(它确实正确地检查了这个线程 )。 The problem lies in your understanding of a keypress on your keyboard, the translation into keycodes, the translation of keycodes into characters and how the ReadKey() method works. 问题在于您对键盘上的按键理解,键码的转换,键码到字符的转换以及ReadKey()方法的工作方式。

First of all: if you want to read consecutive characters, use Console.ReadLine() instead, it does all the math for you, and better. 首先:如果您想读取连续的字符,请改用Console.ReadLine() ,它可以为您完成所有数学运算,而且效果更好。

Let's take a look at the following program: 让我们看一下以下程序:

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();
}

It reads a key from the input, than it appends it to string. 它从输入中读取键,然后将其附加到字符串。 Nothing to worry, right? 不用担心,对吧? Wrong! 错误! On a US International keyboard you can do this: 在美国国际键盘上,您可以执行以下操作:

  • Type ` + a becomes à 类型`+ a变为à
  • Type Alt+123 becomes { 类型Alt + 123变为{
  • Type Alt+3355 becomes ← 类型Alt + 3355变为←
  • Type ; 类型; as if on a Spanish keyboard, becomes ñ 就像在西班牙键盘上一样,变成ñ

Depending on your keyboard, you will hit a different key for a certain character. 根据您的键盘,您将为特定字符按下不同的键。 Sometimes you will hit a combination of keys. 有时您会按下组合键。 The first combination above is recorded as \\0a as a string and keycode 0 (not in the enum) and then ConsoleKey.A . 上面的第一个组合记录为\\0a作为字符串和键码0 (不在枚举中),然后记录为ConsoleKey.A The total resulting string is now "\\0á{←ñ" . 现在,总的字符串为"\\0á{←ñ"

The Alt+123/3355 is recorded as a keycode 18 (this is the Alt-key). Alt + 123/3355被记录为键码18(这是Alt键)。 The translation of the numeric keys to a character is done by the OS before it is send to the console. 将数字键转换为字符是由操作系统完成的,然后再将其发送到控制台。

Typing ; 打字; on a US keyboard or ñ on a Spanish keyboard will show you the ConsoleKey.Oem1 (US) and ConsoleKey.Oem3 (Spanish). 在美国键盘上或在西班牙键盘上的ñ上将显示ConsoleKey.Oem1 (美国)和ConsoleKey.Oem3 (西班牙语)。

While I cannot mimic your behavior, this is probably because I don't have your screen, but it seems very much that the font you have as Console font doesn't support non-Unicode characters. 尽管我无法模仿您的行为,但这可能是因为我没有您的屏幕,但是您作为控制台字体拥有的字体似乎非常不支持非Unicode字符。 On Windows 7, by default it does, I don't know for other Windows versions. 在Windows 7上,默认情况下是这样,对于其他Windows版本我不知道。 It is also possible that the codepage of your console is set incorrectly. 控制台的代码页也可能设置不正确。

To summarize 总结一下
What constitutes a character is dependent on keyboard layout, selected keyboard in international settings, selected language, selected code page in the Console and whether or not combinations of keys are allowed (it gets worse with IME!). 字符的构成取决于键盘布局,在国际设置中选择的键盘,选择的语言,在控制台中选择的代码页以及是否允许使用按键组合(对于IME情况更糟!)。 To go from KeyChar to normal char is often trivial, but depends on whether your system settings are in sync with each other. 从KeyChar转换为普通char通常很简单,但这取决于您的系统设置是否彼此同步。

When I run your examples on my system, I do not have the same behavior. 当我在系统上运行您的示例时,我没有相同的行为。 But then again, I don't have your system. 但是话又说回来,我没有您的系统。

Going from a key to a character is tricky business. 从钥匙变成角色是一件棘手的事。 I suggest you don't rely on your own ability to reinvent what's already in the system. 我建议您不要依靠自己的能力来重新发明系统中已经存在的功能。 It's good practice to try to see what's going on, but really, move back to ReadLine ;). 尝试查看正在发生的事情是一个好习惯,但实际上,请移回ReadLine ;)。

EDIT: 编辑:
I just saw your latest edit. 我刚刚看到了您的最新编辑。 Note that you can have different encodings for input and output ( Console.InputEncoding and Console.OutputEncoding ). 请注意,您可以为输入和输出使用不同的编码( Console.InputEncodingConsole.OutputEncoding )。 I'd also like to quote the other thread to emphasize that when you switch to Unicode, the codepage doesn't matter anymore. 我还想引用另一个线程来强调,当您切换到Unicode时,代码页不再重要。 This is the default behavior on recent Windows versions: 这是最新Windows版本上的默认行为:

If you select a Unicode font, such as Lucida Console or Consolas, then you will be able to see and type Unicode characters on the console, regardless of what chcp says: 如果选择Unicode字体(例如Lucida Console或Consolas),则无论chcp表示什么,您都可以在控制台上查看并键入Unicode字符:

ReadLine() reconfigures the codepage to use properly the extended ASCII and Unicode characters. ReadLine()重新配置代码页以正确使用扩展的ASCII和Unicode字符。 ReadKey() leaves it in EN-US default (codepage 850). ReadKey()保留为EN-US默认设置(代码页850)。

Just use a codepage that prints the characters you want, and that's all. 只需使用打印所需字符的代码页即可,仅此而已。 Refer to http://en.wikipedia.org/wiki/Code_page for some of them :) 有关其中某些内容,请参见http://en.wikipedia.org/wiki/Code_page :)

So, for the Ñ key press, the solution is this: 因此,对于Ñ键按下,解决方案是这样的:

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);

Simple :) 简单:)

And a side note: in some cases it's also necessary to reconfigure the Console.InputEncoding property! 还有一个注意事项:在某些情况下,还必须重新配置Console.InputEncoding属性!

Also, note that if you select another font for the console (Lucida Console/Consolas), this trouble STILLS happen. 另外,请注意,如果您为控制台选择另一种字体(Lucida Console / Consolas),则仍会发生此问题。 Lotta thanks to user Abel for this, he appointed to the font changing for solution and made myself discover that this is false . Lotta感谢用户Abel的帮助,他委托字体更改解决方案,使自己发现这是false

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM