通过JNI实现Java中的非阻塞输入 [英] Non-Blocking Input in Java realized through JNI

查看:60
本文介绍了通过JNI实现Java中的非阻塞输入的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在追求使用Java设计命令外壳.我必须立即实现的一项重要功能是自动完成",这是在按下"tab"键时通过命令外壳实现的.为此,我认为我必须在非阻塞模式下逐字符读取输入命令.

I am in the pursuit of designing a command-shell using Java . One important feature which I had to immediately implement was "auto complete" , as facilitated by the command-shell when "tab" key is being pressed . For this , I reckoned I had to read the input-command, character-by-character in the non-blocking mode .

不幸的是,据我所知,Java API都不支持非阻塞输入.也就是说,用于读取输入的Java API会等待(块),直到用户按下"Enter"键为止,这在我的情况下是非常不希望的.此外,我已经下定决心不使用任何第三方Java库(例如JLine).

Unfortunately , as I have understood , none of the Java API's support non-blocking input . That is , Java API's that are meant to read the input waits (blocks) until the user hits the "Enter" key , which is highly undesirable in my case .Also ,I have made up my mind not to use any third party Java libraries ( Such as JLine ).

所以,我不得不求助于JNI.本机.C文件似乎是这个-

So , I had to resort for JNI . The native .C file appears to be this -

 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方法:

And the corresponding Java method in which the afore-mentioned native method is invoked :

 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.

Also I can assure you that there are no hassles with respect to linking the native .dll . And , the "InterruptableCharacterArray" , as of now contains only '\t'( The "tab" key ). Hence , value of index as of now is 1 .

问题:

1>控件似乎没有在处阻塞:

1> The control doesn't seem to block at :

char variable = (char) read_character();

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

That is , it doesn't seem to allow the user to enter the input through the Java Console at that line , which is intended to do that . And , same is the problem even in the case of getche() ( Non-blocking but echoes )

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

Instead , in each iteration some default garbage value is being taken for "variable" and that is being printed on the console when the following statement is executed :

System.out.println(variable);

但是,当用getc(stdin),getchar()等受阻的替代方法代替getch()时,我的这段代码就像一种魅力.

However , this code of mine works like a charm when getch() is replaced by its blocking counterparts like getc(stdin),getchar() etc .

我无法弄清楚通过JNI调用getch()到底是什么问题.

I am not able to figure-out as to what exactly is the problem in invoking getch() through JNI .

2>另外,如果提出任何其他替代解决方案的建议,我将不胜感激.

2> Also , I would be grateful , if any other alternateive solutions to achieve the same are suggested .

提前谢谢!

命令外壳将同时在基于Windows和Unix的O/S上实现.

推荐答案

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

Before you can have non-blocking IO from a terminal, you need to put it into "raw" mode: Terminals usually collect one line of input (that way, you can edit the current line with the cursor keys, etc) and just send it to the stdin of the application when it's "finished" (= when the user presses enter).

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

In "raw" mode, any keypress is sent to the app immediately and editing isn't possible (unless the app implements it itself).

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

To enable this, see the manual for stty(1). To modify the mode, you will need the C function tcsetattr(3).

我建议即使您不想使用JLine2的源代码,专门放入 UnixTerminal.java TerminalLineSettings

I suggest to look into the source for JLine2 even when you don't want to use it, specifically into UnixTerminal.java and TerminalLineSettings

这篇关于通过JNI实现Java中的非阻塞输入的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆