2012-01-05 15 views
9

ProcessBuilderによって作成された1つのプロセスの出力を別のProcessBuilderで作成された別のプロセスに渡すことはできますか?たとえば、このシェルコマンドを実行しようとしている場合:ProcessBuilderの別のProcessBuilderへのパイプ出力

ls | grep build.xml 

ProcessBuilderでどのようにすればよいですか?

Process process = Runtime.getRuntime().exec("ls"); 
InputStream is = process.getInputStream(); 
byte[] buf = new byte[1000]; 
is.read(buf); 
String parameter = new String(buf); 
System.out.println("grep build " + parameter); 

Process proc2 = Runtime.getRuntime().exec("grep build " + parameter); 
InputStream is2 = proc2.getInputStream(); 
byte[] buf2 = new byte[1000]; 
is2.read(buf2); 
String result = new String(buf2); 
System.out.println("proc2 result: " + result); 

が、それは別の結果は、私はシェルでスクリプトを直接実行したときと比較生成:@erdincが提案されているよう

、私はこれを試してみました。どこが間違っていたのですか?解決

:パラメータ第二の方法として渡すよりも、あなたはのgetInputStreamメソッドを使用することができフィリップ・ウェンドラーソリューション

答えて

6

解決策の問題は、lsの出力から最初の1000バイトだけを読み取り、それらをgrepに渡すことです。 lsからの出力の量がわからないので、それが使い果たされるまでそれを繰り返し読む必要があります。ここで

はgrepのに出力の各行を送信するBufferedReaderのを使用してソリューションです:もちろん

Process lsProcess = Runtime.getRuntime().exec("ls"); 
BufferedReader lsOutput = new BufferedReader(new InputStreamReader(lsProcess.getInputStream())); 
Process grepProcess = Runtime.getRuntime().exec("grep build.xml"); 
BufferedWriter grepInput = new BufferedWriter(new OutputStreamWriter(grepProcess.getOutputStream())); 

String line; 
// read each line from ls until there are no more 
while ((line = lsOutput.readLine()) != null) { 
    // and send them to grep 
    grepInput.write(line); 
    grepInput.newLine(); 
} 

// send end-of-file signal to grep so it will terminate itself 
grepInput.close(); 

あなたは適切なエラー処理ここを追加する必要があります。 このソリューションが遅すぎる場合は、ReaderとWriterを省略して、出力ストリームへの入力から直接byte[]配列を渡すことができます。

しかし、はるかに良い解決策は、ファイルシステムでファイルを探すのにlsとgrepを使うのではなく、適切なJava APIを使うことです。たとえば、目的のディレクトリにFileオブジェクトを作成する場合は、さまざまなディレクトリにあるlistFilesメソッドを使用して、このディレクトリ内のすべてのファイルを一覧表示できます。この方法ははるかに簡単で、移植性があり、エラーが起こりにくく、おそらく高速です。

+0

あなたのソリューションは機能します!ありがとうPhilipp:D私は実際にこのコードを使用して、chasenやmoses(機械翻訳ツール)などのいくつかの外部アプリケーションを呼び出します。 ls | grep exampleは単に質問を簡略化することを目的としていましたが、提案に感謝します:D私は解決された問題をマークし、あなたの解決策をupvoteします。 – ndriks

0

を参照してください。 例コード。

 process = Runtime.getRuntime().exec("ls"); 
     InputStream is = process.getInputStream(); 
     byte[] buf = new byte[1000]; 
     is.read(buf); 
     String parameter = new String(buf); 
     System.out.println(parameter); 
     Runtime.getRuntime().exec("grep build.xml " + parameter); 
+0

"ls"入力ストリームを "grep"プロセスに渡すにはどうすればよいですか?プロセス内のメソッドsetInputStreamを見つけることができません。また、ProcessBuilderで行うこともできますか? – ndriks

+0

私はあなたのソリューション@erdincを試しましたが、それはシェルで直接コマンドを実行するのとは異なる結果を生み出します。私は何をしたかを示すために質問を編集しました。 FYI、lsの結果をパラメータとしてgrepを実行しようとしていませんが、lsの結果をgrepプロセスにパイプしています。 – ndriks

関連する問題