2013-02-27 99 views
0

我在追求使用Java設計命令外殼。我必須立即實現的一個重要功能是「自動完成」,正如按下「tab」鍵時由命令shell提供的那樣。爲此,我估計我必須在非阻塞模式下逐字讀取輸入命令。通過JNI實現的Java中的非阻塞輸入

不幸的是,據我所知,沒有一個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」鍵)。因此,截至目前的指數價值爲1。

萬阿英,蔣達清:

1>控制似乎並不阻止在:

char variable = (char) read_character(); 

也就是說,它似乎沒有允許用戶通過Java進入輸入該線路上的控制檯,旨在實現這一點。而且,即使在getche()(無阻塞但回聲)的情況下,問題也是如此。

相反,在每次迭代中,某些默認垃圾值是針對「變量」進行的,並且正在控制檯上打印下面的語句執行:

System.out.println(variable); 

然而,我的這個代碼的工作就像一個魅力時的getch()被其阻止同行更換喜歡的getc(標準輸入)的getchar()等。

我無法弄清楚究竟是通過JNI調用getch()的問題。

2>另外,如果有其他解決方案可以實現,我將不勝感激。

預先感謝您!

編輯:命令外殼將在基於Windows和Unix的O/S上實現。

+0

你想要的是不是「非阻塞」的IO,但「原始」終端IO。我建議你看看stty – Ingo 2013-02-27 10:53:10

+0

@Ingo:非常感謝!那麼對於Windows O/S呢? – bsv0099 2013-02-27 15:28:09

+0

請注意亞倫發佈的鏈接。 JLine2顯然也可以處理Windows終端,所以你可以在那裏獲得想法。順便說一句,要成爲堆棧溢出的優秀人物,你應該投票贊成有用的答案並接受最好的答案。我認爲亞倫的帖子值得這個。 – Ingo 2013-02-27 15:47:55

回答

1

在你可以從終端獲得非阻塞IO之前,你需要把它置於「原始」模式:終端通常會收集一行輸入(這樣,你可以用光標鍵編輯當前行,等等),並在「完成」時(=當用戶按下輸入時)將它發送到應用程序的標準輸入。

在「原始」模式下,任何按鍵都會立即發送到應用程序,並且不可能進行編輯(除非應用程序自己實現)。

要啓用此功能,請參閱stty(1)的手冊。要修改模式,您需要使用C功能tcsetattr(3)

我建議尋找到了source for JLine2,即使你不想使用它,特別是爲UnixTerminal.javaTerminalLineSettings

+0

非常好,但有一點你錯了:在烹飪模式下,你不能用光標鍵編輯命令行,只能使用DEL或Backspace鍵。這是原始的,noecho模式,使程序可以使用光標鍵進行編輯。 – Ingo 2013-02-27 11:17:33

+0

@Ingo:是的,你對Unix很合適。該shell通過在Unix上將終端置於raw/noecho模式來實現編輯。在Amiga上,終端擁有自己的編輯功能。爲了移植unix shell,我們必須用'stdin.readline()'替換這個代碼:-) – 2013-02-27 12:34:56

+0

@AaronDigulla - 非常感謝!我會朝那個方向努力。另外,你可以告訴我如何在Windows操作系統中使用它嗎? – bsv0099 2013-02-27 15:25:58