在类Unix系统的Java中读取控制台输入时检测Ctrl键状态
Linux终端Java库的非阻塞键盘输入解析问题
我正在编写一个面向Linux终端的Java小型库,需要实现通过System.in以非阻塞方式读取键盘输入的方法。目前已经通过JNA调用libc的tcgetattr()和tcsetattr()函数,成功将终端设置为raw或non-canonical模式。
当前实现逻辑
首先将System.in包装为BufferedReader:
BufferedReader input = new BufferedReader(new InputStreamReader(System.in));
随后读取缓冲区内容到char[]数组并解析:
if (input.ready()) { char[] chars = new char[4]; // 任何有效组合键最多4个字符 int result = input.read(chars, 0, 4); if (result == -1) { // EOF ... } if (result == 1) { // 普通字符 ... } if (result == 2) { if (chars[0] == '\033') { // alt + 字符 ... } if (chars[0] == '^') { // ctrl + 字符 ... } } if (result == 3 || result == 4) { // 特殊字符——光标键、Home、End等 ... } } return null;
遇到的问题
这套逻辑基本符合预期,但无法正确检测Ctrl+键组合(Alt+键组合可以正常处理)。
我能通过以下代码检查单个Ctrl+键组合:
public char ctrlKey(char c) { return (char) (c & 0x1f); // 借鉴自curses库 :-) }
之后在代码中这样检测:
if (c == ctrlKey('x')) { // 执行操作 }
这种方式虽然可行,但如果客户端要实现类似GNU Readline的组合键功能,这类检测逻辑应该由客户端来完成。我希望返回一个包含所有必要信息的KeyStroke类实例(KeyType是枚举,列出所有特殊键):
public class KeyStroke { public final char c; public final boolean alt; public final boolean ctrl; public final KeyType type; public KeyStroke(char c, KeyType keyType, boolean ctrl, boolean alt) { this.c = c; this.alt = alt; this.ctrl = ctrl; this.type = keyType; } }
我的疑问是:是不是除了在输入解析方法中写一个庞大的switch语句来检测所有可能的Ctrl+键组合之外,几乎没有其他办法?这种方式既笨拙又不优雅。
更新
我查看了@DevilsHnd推荐的JNativeHook,它虽然适用于部分场景,但依赖X11,无法在SSH远程会话、纯文本模式(比如无图形界面的服务器)或Wayland环境中工作。
内容的提问来源于stack exchange,提问作者Shovel_Knight
相关产品推荐
相关产品推荐

