使用 Console.ReadKey 读取 Unicode
是否可以向控制台应用程序提供 Unicode 输入,并通过 Console.ReadKey() 读取 Unicode 字符/字符串?
我知道 Unicode 在通过其他方法读取输入时可以工作,但不幸的是我需要使用 ReadKey 提供的“拦截”功能。
更新:
将 U+03BB (λ) 等 Unicode 字符粘贴到控制台时,会读取 3 个键。
- Alt + NumPad1
- Alt + NumPad1
- Alt + NumPad8
我尝试查看这是否是某种编码,但看不到任何内容。
Is it possible to provide Unicode input to a console app, and read the Unicode char/string via Console.ReadKey()?
I know Unicode works when reading the input via other methods, but unfortunately I need to use the 'interception' feature provided by ReadKey.
Update:
When pasting a Unicode character such as U+03BB (λ) into the console, 3 keys are read.
- Alt + NumPad1
- Alt + NumPad1
- Alt + NumPad8
I have tried to see if this is some kind of encoding, but can not see anything.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
不幸的是,Console.ReadKey 只能处理键盘事件。 键盘事件只能表示可以在键盘上键入的内容(使用 ConsoleKey 枚举中定义的真实键和“虚拟”键)。 因此,当使用 ReadKey 时,您只会得到两件事:原始键码(对应于键盘上的键)和翻译字符,即原始键码在控制台的输入代码页中映射到的 Unicode 字符(以及每个代码页最多可以映射 256 个字符)。 您无法使用 ReadKey 读取任何其他类型的数据(即无法直接键入的字符和/或在输入代码页中没有映射的字符)。
此外,当您将 Unicode 字符粘贴到控制台时,ReadKey 使用的 API 会尝试将该字符转换为 Windows ALT+nnn 序列(即,按住 ALT 并在键盘上键入代码点编号)。 不幸的是,它首先使用为输入代码页定义的规则翻译字符,因此即使您重新构建代码点编号,您也不会获得粘贴的实际字符,您将获得代码页映射它的任何字符到。
使用 Read 或 ReadLine 时一切正常的原因是这些是基于流的方法,而不是基于键盘的方法。 显然,任何字符都可以通过输入流进入,因为没有发生键盘和代码页转换。 但是您无法直接使用 ReadKey 获取输入流,只能使用键盘(如果输入流已从键盘以外的其他位置重定向,ReadKey 将彻底失败)。
如果您手动将控制台 API 与 P/Invoke 一起使用,则可能有某种方法可以使用输入流复制 ReadKey 的“拦截”功能,但这并不简单,而且控制台并不是真正设计用于执行此类操作的所以你可能会一直与之抗争。
编辑:尽管如此,您仍然可以实现自己的组合键,以允许通过键盘输入 Unicode 字符 - 例如键入 CTRL+ALT+U,然后输入四个十六进制数字 - 您的 ReadKey 例程可以检测到 CTRL+ALT +U,然后抓住接下来的四个击键并从中创建一个 int 并将其转换为 char ——但这当然不允许粘贴。
Unfortunately, Console.ReadKey is only able to process keyboard events. Keyboard events can only represent things that can be typed on the keyboard (using the real and "virtual" keys defined in the ConsoleKey enumeration). So when using ReadKey you will only get two things: a raw key code, which corresponds to a key on the keyboard, and the translated character, which is the Unicode character that the raw key code maps to in the console's input code page (and each code page can map a maximum of 256 characters). You cannot read any other type of data (namely characters that cannot be directly typed and/or do not have a mapping in the input code page) with ReadKey.
Moreover, when you paste a Unicode character into the console, the API used by ReadKey attempts to translate the character into a Windows ALT+nnn sequence (i.e., hold down ALT and type the code point number on the keypad). Unfortunately, it translates the character first, using the rules defined for the input code page, so even if you reconstitute the code point number you won't get the actual character that was pasted, you'll get whatever character the code page maps it to.
The reason it all works when using Read or ReadLine is that these are stream-based, rather than keyboard-based, methods. Obviously any character whatsoever can come in via the input stream, since there is no keyboard and code page translation happening. But you cannot get at the input stream directly using ReadKey, only the keyboard (and if the input stream has been redirected from somewhere other than the keyboard, ReadKey will fail outright).
There may be some way to replicate the "intercept" functionality of ReadKey using the input stream if you manually use the console API with P/Invoke, but it would be nontrivial, and the console isn't really designed to do that sort of thing so you'd probably be fighting it the whole way.
Edit: All that said, you could still implement your own key combinations to allow Unicode characters to be entered via the keyboard -- such as type CTRL+ALT+U and then four hex digits -- your ReadKey routine could detect the CTRL+ALT+U and then grab the next four keystrokes and make an int out of them and convert it into a char -- but of course this wouldn't allow for pasting.
Console.ReadKey() 返回的 ConsoleKeyInfo 对象有一个名为 KeyChar 的属性,其中包含按下的键或组合键的 Unicode 字符(如果该键或组合键具有等效的 Unicode)。 所以...
如果该键没有 Unicode 等效项(例如功能键),您将得到一个“\0”字符。
如有必要,您可以使用 StringBuilder 将这些字符连接在一起形成 Unicode 字符串。
The ConsoleKeyInfo object returned by Console.ReadKey() has a property called KeyChar containing the Unicode char of the pressed key or key combination (if the key or key combination has a Unicode equivalent). So...
You'll get a '\0' char if the key doesn't have a Unicode equivalent (for example, a function key).
You can use a StringBuilder to concatenate these chars together into a Unicode string if necessary.
现在这很奇怪。 IIRC 我的测试是在 32 位上进行的,可能是 Vista。
现在在 Win7 64 位上进行了相同的测试,该死的东西有效!
所以要么是 Vista 要么是 32 位错误。
有人可以确认一下吗?
Now this just weird. IIRC my testing was on 32-bit, probably Vista.
Now tested the same on Win7 64-bit, the bloody thing works!
So either a Vista or 32-bit bug.
Can someone please confirm this?