2012-04-25 3 views
0

標準入力からデータを必要とすることがありますが、時にはJavaでデータを要求しないことがありますか?私は、コマンドラインで標準入力からSQL文を読むために以下のコードを使用しています

BufferedReader in = null; 
    StringBuilder sb = new StringBuilder(); 
    String line = null; 
    try { 
     in = new BufferedReader(new InputStreamReader(System.in)); 
     while((line = in.readLine()) != null) { 
      sb.append(line); 
     } 
    } finally { 
     if (in!=null) in.close(); 
    } 

私の問題は、アプリケーションが時々いない(なしパイプによる入力)標準入力からデータを時々実行する必要があり、ということです。上記のコードに入力がない場合、in.readLine()ブロック。何もパイプされていない場合でも実行できるように、このコードを書き換える方法はありますか?

更新:アプリケーションは、キーボードからではなく、コマンドラインからパイプされたデータを期待するように設計されています。

+0

標準入力はコンソールを表します。ユーザーが何かを入力するかどうかは、どのようにして知ることができますか? –

+0

感謝のピーター - 明確にするために質問を更新しました。 –

+0

その場合、in.readLine()はファイルシステムからのデータを待っている間のみブロックします。これは非常に短くなければなりません(約10ミリ秒)私はあなたのファイルシステムが非常に遅いです、これはほとんどの時間をブロックしているように見えるかもしれませんが、実際にはデータを処理してディスクを繰り返し待っています。 –

答えて

2

最終的に別の入力行があるかどうかを確認する方法はないと思います。ユーザーが入力ストリームを閉じると(たとえば端末の^ Dで)現在のコードが終了することに注意してください。

BufferedReader.ready()は、ストリームにデータがあるかどうかを確認します。 T.Jのように。あなたが実際にそれを受け取る直前に不運に思ってデータを尋ねるかもしれませんし、あなたの質問に答えなかったのであなたのユーザーは悲しいでしょう。

Scanner.hasNextLine()はブロック操作であるため、探しているものとは異なる可能性があります。

たとえば、コマンドライン引数を使用してSystem.inから読み込むかどうかをユーザーに指定させることができます。

+0

完全に機能したBufferedReader.ready()を使用してしまいました。ありがとう! –

+0

これについて少し詳しく説明します。これは、入力がすぐに 'BufferedReader'で利用できるときにのみ正しく動作することがわかりました。たとえば、 'ready()'のようなデータベースに問い合わせるコマンドラインツールからのデータをパイプすると、データベースへのラウンドトリップに数msかかるので、直ちにfalseを返します。代わりに、私はあなたが示唆したようにコマンドライン引数をコード化しなければならなかった。 –

2

readyを使用すると、ストリームにデータが準備されているかどうかをテストできます。 readyfalseを返す場合は、コール時にストリームにデータ準備ができていません(後でマイクロ秒でデータを受信した可能性があります)。 readyに電話してtrueを返すと、ブロックせずにreadに電話することができます。 (ブロックすることなくreadLineに電話することはできません)

1

オプションで標準入力からの読み取りをサポートするUnixユーティリティは、通常、コマンドラインに基づいて何をすべきかを判断します。たとえば、コマンドラインでファイル名が指定されていない場合、catはstdinから読み込みます。あなたはこれらの行に沿って何かをすることができます - プログラムがstdinから何かを読み込もうとしなければならないかどうかを示すためにコマンドラインのフラグやオプションを追加してください。

もう1つの方法は、プログラムに読み込ませる入力がない場合は、/ dev/nullからの入力をリダイレクトすることです。この場合、stdinから読み込み、ファイルの終わりの指示をすぐに得ることができます。同等のウィンドウはNULからリダイレクトされます。

ブロッキングせずにstdinから読み込めるかどうかを検出するプログラムが本当に必要な場合は、InputStream.available()をご覧ください。しかし、プログラムの入力を誰かがサポートしたい場合(または端末ウィンドウにコピーして貼り付ける)、InputStreamはユーザーが実際に何かを入力するまで入力を表示しません。

+0

また、多くのunix utilsは "stdin"を意味する "特別な"入力ファイル - をサポートしています。 – jtahlborn

0

パイプ入力がない場合、プログラムの実行方法によって異なります。一般的に、プログラムはオープンスタンダードを持ち、タイマーを設定し、一定時間入力を待つだけです。タイマーが入力なしで終了する場合、何も起こらないと仮定します。別の方法は、stdinを閉じた状態で実行するようにプログラムを調整することです。その場合は、読み込みを試みるときにEOFを取得します。

あなたがプログラムを起動するbashスクリプトを記述します(MacのOSを含む)UNIXで標準入力を閉じるには:もちろん

#!/bin/bash 

exec 0>&- # close stdin 

java -jar yourProgram.jar # run your program 

、とにかくbashコマンドラインから起動している場合、あなたドン「がtは、スクリプトを必要とする:

prompt> java -jar yourProgram.jar 0>&- 

しかし、あなたのプログラムは、Java EEコンテナ内で実行されている場合、私はあなたが起動する前にSTDINを閉じたいのか分からないし、多分あなたはできません。

0

unixでは、/proc/self/fd/0がファイル、パイプ、またはコンソールを指しているかどうかを確認できます。

$ ls -l /proc/self/fd/0 
lrwx------ 1 peter peter 64 Apr 25 18:12 /proc/self/fd/0 -> /dev/pts/21 
$ ls -l /proc/self/fd/0 < /dev/null 
lr-x------ 1 peter peter 64 Apr 25 18:13 /proc/self/fd/0 -> /dev/null 
$ echo Hello World | ls -l /proc/self/fd/0 
lr-x------ 1 peter peter 64 Apr 25 18:13 /proc/self/fd/0 -> pipe:[139250355] 

入力がパイプされた、ファイルであるかの端末である場合、これはあなたを教えてくれます。

関連する問題