0

私はJavaを使用してコマンドシェルを設計することを追求しています。私がすぐに実装しなければならなかった重要な機能の1つは、「タブ」キーが押されているときにコマンドシェルによって促進される「オートコンプリート」でした。このために、私は、非ブロッキングモードで入力コマンドを文字ごとに読み取る必要があると考えました。

残念ながら、私が理解しているように、JavaAPIはいずれも非ブロッキング入力をサポートしていません。つまり、ユーザーが「Enter」キーを押すまで入力待機(ブロック)を読み取ることを目的としたJava APIは、私の場合は非常に望ましくありません。また、サードパーティの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です。

Probelm:

1>コントロールがブロックされていないようです:

char variable = (char) read_character();

つまり、ユーザーがその行でJavaコンソールを介して入力を入力することを許可していないようです。これはそれを行うことを目的としています。そして、getche()の場合でも同じ問題があります(ノンブロッキングですがエコーします)

代わりに、各反復で「変数」に対してデフォルトのガベージ値が取得され、次のステートメントが実行されたときにコンソールに出力されます。

System.out.println(variable);

ただし、この私のコードは、getch()がgetc(stdin)、getchar()などのブロックする対応物に置き換えられたときに魅力のように機能します。

JNIを介してgetch()を呼び出す際の問題が正確に何であるかを理解することはできません。

2>また、同じことを達成するための他の代替ソリューションが提案された場合、私は感謝します。

前もって感謝します !

編集:コマンドシェルは、WindowsとUnixベースのO/Sの両方に実装されます。

4

1 に答える 1

1

端末から非ブロッキング IO を使用する前に、「生」モードにする必要があります。端末は通常、1 行の入力を収集し (カーソル キーなどを使用して現在の行を編集できます)、送信するだけです。アプリケーションが「終了」したとき (= ユーザーが Enter キーを押したとき) に、アプリケーションの stdin に追加します。

「生」モードでは、キーを押すとすぐにアプリに送信され、編集はできません (アプリ自体が実装されている場合を除く)。

これを有効にするには、 のマニュアルを参照してくださいstty(1)。モードを変更するには、C 関数が必要ですtcsetattr(3)

JLine2を使用したくない場合でも、ソース、特にUnixTerminal.javaTerminalLineSettingsを調べることをお勧めします。

于 2013-02-27T11:03:01.833 に答える