我正在寻求使用Java设计命令shell。我必须立即实现的一个重要特性是“自动完成”,当按下“tab”键时由命令shell促成。为此,我估计我必须在非阻塞模式下逐个字符地读取输入命令。
不幸的是,正如我所理解的,Java API都不支持非阻塞输入。也就是说,Java API用于读取输入等待(块),直到用户点击“Enter”键,这在我的情况下是非常不受欢迎的。另外,我已经决定不使用任何第三方Java库(如JLine)。
所以,我不得不求助于JNI。原生.C文件似乎是这个 -
JNIEXPORT jint JNICALL Java_autoComplete_IOUtils_read_1character(JNIEnv *env, jobject obj)
{
int ch = getch(); // getch() - non-blocking input and doesn't echo the characters
return (jint)ch;
}
以及相应的Java方法,其中调用了上述本机方法:
public static String GetLine()
{
int i = 0;
do
{
char variable = (char) read_character(); // Native method is invoked here
System.out.println(variable); // Just printing it for my reference
cmdLine = new StringBuffer(cmdLine).insert(i, variable).toString(); // cmdLine is of type String
i++;
} while ((search(cmdLine.charAt(i - 1), interruptableCharacterArray)) == false);
return (new String(cmdLine));
}
//Checks if the entered character is any one of those keys in the interruptableCharacterArray . As of now , interruptableCharacterArray contains only '\t' (The tab key )
private static boolean search(char charAt,char[] interruptableCharacterArray2)
{
for (int i = 0; i < index; i++)
{
if (interruptableCharacterArray2[i] == charAt)
return true;
}
return false;
}
此外,我可以向您保证,在链接原生.dll方面没有麻烦。而且,“InterruptableCharacterArray”,截至目前只包含'\ t'(“标签”键)。因此,截至目前的指数值为1.
Probelm:
1&GT;该控件似乎没有阻止:
char variable = (char) read_character();
也就是说,它似乎不允许用户通过Java控制台在该行输入输入,这是为了做到这一点。而且,即使在getche()(非阻塞但回声)
的情况下,问题也是如此相反,在每次迭代中,一些默认的垃圾值被用于“变量”,并且在执行以下语句时正在控制台上打印:
System.out.println(variable);
然而,当getch()被其阻塞对象(如getc(stdin),getchar()等)取代时,我的这段代码就像魅力一样。
我无法弄清楚通过JNI调用getch()究竟是什么问题。
2 - ;此外,如果有任何其他替代解决方案可以提出,我将不胜感激。
提前谢谢!
编辑:命令shell将在基于Windows和Unix的操作系统上实现。
答案 0 :(得分:1)
在从终端获得非阻塞IO之前,您需要将其置于“原始”模式:终端通常收集一行输入(这样,您可以使用光标键编辑当前行等)并在它“完成”时(=当用户按下回车键时)将其发送到应用程序的标准输入。
在“原始”模式下,任何按键都会立即发送到应用程序并且无法进行编辑(除非应用程序自己实现)。
要启用此功能,请参阅stty(1)
的手册。要修改模式,您需要C函数tcsetattr(3)
。
我建议您查看source for JLine2,即使您不想使用它,特别是UnixTerminal.java和TerminalLineSettings