0

我正在追求使用 Java 设计一个命令外壳。我必须立即实现的一项重要功能是“自动完成”,这在按下“tab”键时由命令外壳提供便利。为此,我认为我必须在非阻塞模式下逐个字符地读取输入命令。

不幸的是,据我了解,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”(“tab”键)。因此,截至目前的 index 值为 1 。

问题:

1> 控件似乎没有阻塞:

char variable = (char) read_character();

也就是说,它似乎不允许用户在该行通过 Java 控制台输入输入,而这是打算这样做的。而且,即使在 getche() 的情况下也是同样的问题(非阻塞但回声)

相反,在每次迭代中,“变量”都会采用一些默认垃圾值,并在执行以下语句时将其打印在控制台上:

System.out.println(variable);

但是,当 getch() 被 getc(stdin)、getchar() 等阻塞对应物替换时,我的这段代码就像一个魅力。

我无法弄清楚通过 JNI 调用 getch() 究竟是什么问题。

2> 另外,如果建议任何其他替代解决方案来实现相同的效果,我将不胜感激。

先感谢您 !

编辑:命令外壳将在基于 Windows 和 Unix 的操作系统上实现。

4

1 回答 1

1

在您可以从终端获得非阻塞 IO 之前,您需要将其置于“原始”模式:终端通常收集一行输入(这样,您可以使用光标键等编辑当前行)然后发送当它“完成”时(=当用户按下回车键时)它到应用程序的标准输入。

在“原始”模式下,任何按键都会立即发送到应用程序,并且无法进行编辑(除非应用程序自己实现)。

要启用此功能,请参阅stty(1). 要修改模式,您将需要 C 函数tcsetattr(3)

我建议查看JLine2 的源代码,即使您不想使用它,特别是查看 UnixTerminal.javaTerminalLineSettings

于 2013-02-27T11:03:01.833 回答