• ベストアンサー

ProcessBuilderを使用して、対話型の外部プログラムとやり取りするには?

環境はWindowsXPです。 対話型の外部プログラム、例えば、sqlite3やcygwinのシェルなどを ProcessBuilderを使って対話的にやり取りする方法はありますか? 普通に ProcessBuilder pb = new ProcessBuilder("cmd", "/C", "sqlite3.exe"); としても固まってしまいます。 作りたいもののイメージとしては、eclipseのProcessConsoleのようなものです。 これをeclipseを使わずにSWTのみで作りたいと考えています。

質問者が選んだベストアンサー

  • ベストアンサー
  • PecoPlus
  • ベストアンサー率76% (144/188)
回答No.2

 使ったことないので、よくわからないのですが、sqlite3は、cmd.exeと同じで順次コマンドを入力していくタイプですよね。  たぶん、exit的なコマンドを入力しないと終了しないのだと思います。  すると困ったことに、 while ((line = br.readLine()) != null) {   System.out.println(line); }  ここを抜け出ることはできません。  終了しない限りこのループを抜けられませんし、終了するにはexitコマンドを入力しなくてはいけません。  しかし、コマンドを入力するには、このループを抜けなくてはいけない。  宝箱の中の鍵みたいなことになってます。  問題は、前の質問と同じ、一つのスレッドでどうにかしようとしていることにあります。  サンプル書くとこんな感じでしょうか。  sqlite3がないので、cmd.exe で代用しています。 (コンパイルするときは全角スペースを半角スペースに変換してからにしてください) import java.io.IOException; import java.io.PrintWriter; import java.util.Scanner; public class Main implements Runnable {   Process p;   public static void main(String[] args) {     ProcessBuilder pb = new ProcessBuilder("cmd", "/K");     Process p;     try {       p = pb.start();     } catch (IOException ex) {       ex.printStackTrace();       return;     }     Main main = new Main();     main.p = p;     (new Thread(main)).start();     PrintWriter pw = new PrintWriter(p.getOutputStream(), true);     Scanner in = new Scanner(System.in);     while (in.hasNextLine()) {       pw.println(in.nextLine());     }     in.close();   }   public void run() {     Scanner cmdIn = new Scanner(p.getInputStream());     while(cmdIn.hasNextLine()) {       System.out.println(cmdIn.nextLine());     }     cmdIn.close();     System.exit(0);   } }

kawaby
質問者

お礼

教えて頂いたコードがやりたかった事と一致しています。 Scannerを使って標準入力を取得できるんですね。 重ね重ねありがとうございます。

全文を見る
すると、全ての回答が全文表示されます。

その他の回答 (1)

  • PecoPlus
  • ベストアンサー率76% (144/188)
回答No.1

 こんにちは。  「固まる」とは、どういう状態になっているのでしょうか?  もう少し、詳しくお願いいたします。  また、問題が再現するサンプルコードを補足できないでしょうか?

kawaby
質問者

補足

失礼しました。「固まる」というのはeclipseで強制的に終了ボタンを押さないと、プログラムが終わらないという意味です。 ソースコードは以下になります。 ProcessBuilder pb = new ProcessBuilder("cmd", "/C", "sqlite3"); process = pb.start(); BufferedReader br = new BufferedReader(new InputStreamReader(in)); while ((line = br.readLine()) != null) { System.out.println(line); } br.close(); 上のコードに対し、 OutputStream out = process.getOutputStream(); out.write(".help".getBytes()); のようにして、外部プログラムと対話的にやりとりできないかなと考えています。

全文を見る
すると、全ての回答が全文表示されます。

関連するQ&A

  • JavaAppletのボタンを押すことで、Fortranプログラムが実

    JavaAppletのボタンを押すことで、Fortranプログラムが実行できるようにプログラムを作っています。ですが、今エラーが出て困っています。誰か教えて頂けないでしょうか? 必ず、エラーでディレクトリが見つかりません。とでます。 cdのコマンドでプログラムがある所まで移動したいのですが,どう打てばいいのか分かりません。現在のプログラムは以下のとおりになっています。 OSはLinuxのFedora10です。開発環境としてEclipse使ってます。 try { String command = "./main < input.txt"; //外部プロセス ProcessBuilder pb = new ProcessBuilder(command); //ProcessBuilder構築 Process process = pb.start(); //プロセス実行 process.waitFor(); } catch (Exception e1) { e1.printStackTrace(); }

  • SWTのStyledTextを使用したコンソールの開発

    SWTのStyledTextを使って、コマンドプロンプトのSWT版を作ろうと考えています。 具体的には、Google Androidの「adb shell logcat」の内容をSWTのStyledTextに表示したいのですが、実行するとGUIが固まってしまいます。 期待している動作は、「adb shell logcat」をStyleTextから実行後すると、一度、ログの内容が出力され、そのまま待機します。 その後、ログが出力されてるたびにStyleTextにログが追記されるというものです。 以下は該当箇所のソースです。 String command = "C:/android-sdk-windows-1.5_r1/tools/adb.exe shell logcat"; Display.getCurrent().asyncExec(new Runnable() { @Override public void run() { exec(command); } }); protected boolean exec(String command) { Process process = null; ProcessBuilder pb = new ProcessBuilder("cmd", "/C", command); try { process = pb.start(); InputStream in = process.getInputStream(); BufferedReader br = new BufferedReader(new InputStreamReader(in, "UTF-8")); String line; while ((line = br.readLine()) != null) { if (line.length() == 0) { line = br.readLine(); } // 次も空行なら終了 if (line.length() == 0) { break; } styledText.append(line); styledText.append("\n"); // スクロールバーを下に動かす styledText.setTopIndex(styledText.getLineCount()); } br.close(); } catch (Exception e) { e.printStackTrace(); return false; } return true; }

    • ベストアンサー
    • Java
  • どうしてもプログラムが動いてくれません....

    import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.Reader; import java.io.StringWriter; public class Tese { public static void main(String[] args) throws InterruptedException, IOException { ★ ProcessBuilder pb = new ProcessBuilder("cmd", "/C", "dir", "C:\\Program Files\\Java"); ★ Process p = pb.start(); BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream())); Catcher c = new Catcher(br); c.start(); p.waitFor(); p.destroy(); System.out.println(c.out.toString()); } } class Catcher extends Thread { Reader in; StringWriter out = new StringWriter(); public Catcher(Reader in) { this.in = in; } public void run() { int c; try { while ((c = in.read()) != -1) { out.write((char)c); } } catch (IOException e) { e.printStackTrace(); } } ★で囲んでいる部分なのですが,コンパイルすると Exception in thread "main" java.lang.Error: コンパイル問題が未解決です。 コンストラクター ProcessBuilder(String, String, String, String) は未定義です。 at Tese.main(Tese.java:10) というエラーが出ます. どうすればエラーが消えるかわかる方いらっしゃったら,ぜひ助言頂けないでしょうか・へj

    • ベストアンサー
    • Java
  • JAVAで外部ファイルの実行

    JAVAで外部ファイルを実行したいのですが、 myjbutton.addActionListener(new ActionListener(){ public void actionPerformed(ActionEvent ae){ Runtime myruntime=Runtime.getRuntime(); try{Process myprocess=myruntime.exec("cmd.exe");}catch(IOException e){}; }}); ボタンを押して、実行させたいのですが、これが 全く起動しません。notepad.exeなども試しました が無理でした。 アドバイスがあれば、教えてください。お願いします。

    • ベストアンサー
    • Java
  • ProcessBuilderの使い方

    ProcessBuilderを使用してMysqlのコマンド(Select文、Create文)を実行することはできないか と思い下記サンプルを作ってみました。まづはmysqlを起動するコマンドを実行してみました。 Eclipse上で実行してみたのですが p.waitFor(); の部分で応答が返ってこなくなります。 何か使い方が間違っていますでしょうか。 import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; public class ProcessBuilderTest { public static void main(String[] args) { ProcessBuilder pb = new ProcessBuilder("mysql", "-u", "root", "-p", "root"); try { Process p = pb.start(); // ping が完了するのを待つ p.waitFor(); // 実行結果を取得するストリームの種別を出力 System.out.println(pb.redirectInput()); try (BufferedReader br = new BufferedReader( new InputStreamReader(p.getInputStream()))) { // ping結果の出力 for(String line = br.readLine(); line != null; line = br.readLine()) { System.out.println(line); } } } catch (IOException | InterruptedException e) { // 例外ハンドリング処理 } } }

  • javaからexeの起動、値渡し(?)について。

    1. 短縮したソースで申し訳ないのですが、JavaからC++で作成したexeファイルの、 int secに、javaでexe起動時に任意の数値を渡したいのですが、 何か良い方法はありますでしょうか? 2. またJavaで、外部ファイルを起動した時に、例えばFirefox等の場合、 自身の設定や、お気に入りが全くない状態で起動するのは何故でしょうか? 回答いただければと思います。どうぞよろしくお願いいたします。 [java] ProcessBuilder pb=new ProcessBuilder("C:\\Users\\Super\\Desktop\\cplus.exe", "30"); try { Process p=pb.start(); int ret=p.waitFor(); System.out.println("process exited with value : " + ret); } catch (IOException ioe) { } catch (InterruptedException inte) { } [C++ win32api] #include <windows.h> int main() { int sec=0; HANDLE hTimer; BOOL ret=FALSE; DWORD err=0; //以下はタイマー作成 }

    • ベストアンサー
    • Java
  • cygwin/bashとDOSの共通時間待ち

    timeoutというコマンドがありますが、bashとWindows(DOS)でそれぞれ意味が違います。 DOSのtimeoutでバッチファイルを作り、 DOSでも、cygwin/bashから呼び出しても動作するようにしたかったのですが、 うまく行きませんでした。 たぶん動くだろうと期待した、 cmd.exe /c timeout /T 10 は、cygwin/bashはbashのtimeoutと認識し、DOSのtimeoutとは認識しません。 つまりDOSでは動くのですが、cygwin/bashから起動しても正しく動作しません。 timeoutは、DOSでは少くとも外部コマンドではないと思うのですが、 単純に内部コマンドでもないかもしれません。 しょうがないのでpingを使って両用の待ちを実現していますが、 正直この種の方法は好きではありません。 何かいい方法はありますでしょうか?

  • Javaで外部ファイルの実行

    Javaで外部ファイルの形態素解析ツールのjumanを実行させようとしてるのですが上手くいきません。 ソースは以下のようにしています。 public class CommandExec { /** * 外部コマンドを実行します。 * またリタンーン値で、標準出力、エラー出力 、リターンコードを取得します。 * 例: * execCommand("notepad.exe"); * * @see execCommand(String[] cmds) * ※実行するコマンドに引数(パラメータ)がある場合は、 * 以下を使用してください。 * @param cmd 実行するコマンド * @return コマンド実行結果情報を保持するString配列 * 配列[0] ⇒ 標準出力 * 配列[1] ⇒ エラー出力 * 配列[2] ⇒ リターンコード * @throws IOException 入出力エラーが発生した場合 */ String b; public static String[] execCommand(String cmd) throws IOException, InterruptedException { return execCommand(new String[] { cmd }); } /** * 外部コマンドを引数(パラメータ)を指定して実行します。 * またリタンーン値で、標準出力、エラー出力 、リターンコードを取得します。 * 例: * execCommand(new String[]{"notepad.exe","C:\test.txt"}); * * Process.waitFor()を実行していますので、外部コマンドの実行が * 終了するまでこのメソッドは待機します。 * * @see execCommand(String cmd) * ※実行するコマンドに引数がない場合は簡易的にこちらを * 使用してください。 * @param cmds 実行するコマンドと引数を含む配列 * @return コマンド実行結果情報を保持するString配列 * 配列[0] ⇒ 標準出力 * 配列[1] ⇒ エラー出力 * 配列[2] ⇒ リターンコード * @throws IOException 入出力エラーが発生した場合 */ public static String[] execCommand(String[] cmds) throws IOException, InterruptedException { String[] returns = new String[3]; String LINE_SEPA = System.getProperty("line.separator"); Runtime r = Runtime.getRuntime(); Process p = r.exec(cmds); InputStream in = null; BufferedReader br = null; try { in = p.getInputStream(); StringBuffer out = new StringBuffer(); br = new BufferedReader(new InputStreamReader(in,"sjis")); String line; while ((line = br.readLine()) != null) { out.append(line + LINE_SEPA); System.out.println(line); } System.out.print("\n"); returns[0] = out.toString(); br.close(); in.close(); in = p.getErrorStream(); StringBuffer err = new StringBuffer(); br = new BufferedReader(new InputStreamReader(in)); while ((line = br.readLine()) != null) { err.append(line + LINE_SEPA); } returns[1] = err.toString(); returns[2] = Integer.toString(p.waitFor()); return returns; } finally { if (br != null) { br.close(); } if (in != null) { in.close(); } } } public static void main(String[] args) throws IOException, InterruptedException { ArrayList a = new ArrayList(); CommandExec.execCommand(new String[]{"C:\\Program Files\\juman\\juman.exe","<","C:\\Program Files\\juman\\test1.txt"}); } } これをおなじ解析ツールのchasenを実行した場合は上手くいくのですがなぜでしょうか? chasenの場合は以下のようにしてます。 CommandExec.execCommand(new String[]{"C:\\Program Files\\ChaSen\\chasen.exe","C:\\Program Files\\Chasen\\test1.txt"}); よろしくお願いします。

    • ベストアンサー
    • Java
  • Eclipse>ant deployでOutOfMemory(コマンドラインからはOK)

    ----------環境--------- WindowsXP professional sp2 Eclipse version : 3.2.0 Eclipse build ID: M20060629-1905 jdk:1.4.2_08 ----------------------- コマンドラインからant deployを実行すると BUILD SUCCESSFUL になるのですが、 同じものをEclipseからキックすると、 コンパイルの途中でout of memory エラーとなります。 ヒープサイズを設定することで回避できるとのことなので、 ant.bat には以下の記述をしてあるのですが。。。 java.exe -XX:MaxPermSize=128m -Xmx512m -classpath "%ANT_HOME%\lib\ant-launcher.jar" "-Dant.home=%ANT_HOME%" org.apache.tools.ant.launch.Launcher %ANT_ARGS% %ANT_CMD_LINE_ARGS% これだけでは情報が少ないかもしれませんが、 コマンドラインではOKで、EclipseからはNGという部分で なにかアドバイスが頂けたらと思います。

  • プログラムからコマンドプロンプトを操作

    はじめまして。質問させていただきます WindowsXP Home Edition SP2 GCC 3.4.5 (MinGW) コマンドプロンプトをサポートするようなソフトをイメージしています。 AllocConsole()の後CreateProcessでcmd.exeの起動まではうまくいっています。 やりたいことは、 ■(1)外部のソフトからコマンドプロンプトに対してコマンドを送りたい 例:自作アプリのボタンを押すと"dir"が送られてファイル一覧が表示される ■(2)外部のソフトのキー入力をそのままコマンドプロンプトに送りたい 例:自作アプリ上でキーボードの[a]を押すとコマンドプロンプト上で「C:\>a(カーソル)」のように入力される ■(3)コマンドプロンプトを直接操作したい 例:コマンドプロンプト上でキーボードから[C][D][ ][.][.][Enter]と押してディレクトリを移動する (1)については名前なしパイプのサンプルを発見しとりあえず解決しています。 (2)についても自作アプリ側に発生したメッセージをそのままSendMessageすることでとりあえず乗り切りました。 (3)はコマンドプロンプトの一般的な使い方です。 しかし、(1)を実現すると、(2)、(3)が共にできなくなってしまいます。(コマンドプロンプトが反応しない) これらを全て同時に実現するか、あるいは切り替えて使用する方法を探しています。 パイプの代わりにWriteConsoleInput,SendInputなども考えましたがキーコードしか送れないようなので、全角のテキスト送信には無理かと思っています。(ESCキーの送信などには使えそうです) よろしくお願いします。 参考にしたサイト: ・http://capsulecorp.studio-web.net/tora12/c/api/Console.html ・http://www.fides.dti.ne.jp/~tokai/vc/vcpipe.html (現在のソースはここのサンプルから標準出力の部分を削除したようなものです)