2016-04-18 11 views
1

私はWindows 7マシンで作業しています。Javaでコマンドプロンプトを使用する

私は、HaskellのGHCiインタープリタのフロントアプリケーションです。ユーザーがコマンドを入力すると、Runtimeのexec()メソッドを使用してJavaがコマンドを実行し、コマンドプロンプトを使用してGHCiを実行していた場合に表示されるテキストが表示されます。

今、出力を印刷するループに関する問題が発生しています。

ここに私が今いるコードがあります。 「:http://www.haskell.org/ghc/:?に助けをGHCiの、バージョン7.10.3」

public class GHCiTest { 
public static Scanner rd, sc; 

/** 
* @param args the command line arguments 
*/ 
public static void main(String[] args) { 

try { 

    System.out.println("Starting... "); 

    Process p = Runtime.getRuntime().exec("ghci"); 

    PrintStream hugsin = new PrintStream(p.getOutputStream()); 
    InputStream hugsout = p.getInputStream(); 

    sc = new Scanner(hugsout); 
    rd = new Scanner(System.in); 

    String rdnextline; 



    while (true){ 
    while (sc.hasNextLine()){ 
     System.out.println(sc.nextLine()); 

    } 
     System.out.println("yay"); 
     rdnextline = rd.nextLine(); 
    if (rdnextline == "quit"){break;} 
    hugsin.println(rdnextline); 
    hugsin.flush(); 

    } 
    System.out.println(" ... successful completion."); 
} 
catch(IOException e) { 
    e.printStackTrace(); 
} 
} 

} 

私はプログラムがプリントアウトされるので、GHCiの最初の始動が、動作していることを知っています。しかし、この問題はwhile(sc.hasNextLine())ループのように見えます。これは、コマンドプロンプトの出力を読み込んで何も残らないうちに出力することになっています。ループから抜け出すことはありません。ユーザーの入力を読んでください。プログラムがループの後に入れた "yay"フラグを印刷していないので、私はこれを知っています。

+0

スキャナーの代わりにバッファードリーダーを使用しましたか? – Norsk

+2

'sc.hasNextLine()'はストリーム**の終わりに達するまで待ちます(入力がない場合)...ストリームの終了は、プログラムが終了したときにのみ発生します。 – Codebender

+1

2つの懸念事項:1. GHCiは実際にこのように使用するようには設計されていません。インタラクティブな開発ツールです。インタラクティブなユーザーインターフェイスの詳細に依拠すれば、新しいバージョンが出たときにプログラムが中断する可能性があります。あなたは 'ghc -e'をあなたの目的に使うことができますか? 2. GHCiをウェブに公開するのは、周囲に大きなサンドボックスがある場合を除いて、公開しない方がよいでしょう。完全なGHCiアクセスはフルシェルアクセスに似ています。 – dfeuer

答えて

2

あなたのループは、ストリームの最後まで出るには達していません。

while (sc.hasNextLine()){ 
    System.out.println(sc.nextLine()); 
} 

ストリームの終わりに、あなたのプロセスの終わりです。したがって、あなたのJavaプログラムは、サブプロセスが完了するまで待って終了します。これが起こると、ループは終了し、Javaプログラムはプロセスに目的のコマンドを送信します。

申し訳ありませんが、私は、目的のコマンドをプロセスに送信しようとしています。プロセスが終了したために成功しません。

GHCiプロセスが何らかの種類の「プロンプト」を出力した場合、その時点でwhile(...) { print }を破壊し、ユーザーからの入力を受け取り、プロセスに送信し、ループバックしてwhile(...) { print }次のプロンプトを待つ。

プロンプトが改行で終わらず、ユーザー入力が入力された行の先頭に表示されると仮定すると、プロンプトが完全な行ではないため、while(sc.hasNextLine()) { ... }のループは使用できません。最後の "n"文字のプロンプトシーケンスを探して、文字単位で読む必要があるかもしれません。

GHCiでプロンプトを変更できるようです。 here for detailsを参照してください。プロンプトを改行で終了するように変更した場合でも、ストリームを行単位で読むことができます。

while (sc.hasNextLine()){ 
    String line = sc.nextLine(); 
    if (line.equals("YourPromptHere")) 
     break; 
    System.out.println(line); 
} 

(代わりに、あなたは両方の部分がお互いをブロックすることなく実行できるようにするスレッドで何かを行うことができるかもしれない。もちろん、スレッドは、独自の問題や複雑さが付属しています。)


EDIT

私は明白な瞬間がありました。 GHCのプロンプトを仮定すると、プロンプト文字列Main>ように、スキャナの区切り文字を設定することができ

GHCi, version 7.10.3 
yada, yada, yada ... 
Main> _ 

... ...このようになります。

// Set scanner delimiter to GHCi's Prompt string 
sc = new Scanner(hugsout).setDelimiter("^Main> "); 

while (sc.hasNext()) { 

    // Echo GHCi's output upto the delimiter (prompt) 
    System.out.println(sc.next()); 

    // Read user input & transfer to GHCi. 
    System.out.print("Replacement Prompt> "); 
    rdnextline = rd.nextLine(); 
    if (rdnextline == "quit") { 
     break; 
    } 
    hugsin.println(rdnextline); 
    hugsin.flush(); 
} 

:GHCiのコマンドを完了するために、より多くの入力を想定していたときにこれを考慮に使用される二次プロンプトを取ることはありません。プロンプトに一致する正規表現("^Main> |\bAlt> ")を使用できますが、デリミタが一致したプロンプトを確認することはできません。 "^Main> "は、行の先頭に一致し、その後に「Main>」が続きます.2番目の部分形式の"\bAlt> "は、の単語境界と "Alt>"だけ一致します。これは、GHCiの出力ストリームがのようになり、Alt>の前に長いポーズがあるためです。 Alt>の前の "改行"は、通常、入力ストリームにキー入力されたEnterのエコーから来ます。

+0

ユーザーが入力を入力するまで、どのようにすべてを印刷することができるか知っていますか? – dinstruction

+0

出力ストリームを見て、 'GHCi'からのプロンプトを探します。編集 – AJNeufeld

+0

を参照してください。私は新しい行を受け取った後、ユーザー入力を要求する前にGHCiが印刷するものであるかどうかを確認する必要がありますか?スキャナがInputStream内の次の文字を読み取ることをブロックされているかどうかを判断する一般的な解決法はありますか? – dinstruction

2

このような別のスレッドでghciの出力を受け取ります。

System.out.println("Starting... "); 

Process p = Runtime.getRuntime().exec("ghci"); 

PrintStream hugsin = new PrintStream(p.getOutputStream()); 
InputStream hugsout = p.getInputStream(); 
Scanner rd = new Scanner(System.in); 
new Thread(() -> { 
    try (Reader r = new InputStreamReader(hugsout)) { 
     int ch; 
     while ((ch = r.read()) != -1) 
      System.out.print((char)ch); 
    } catch (IOException e) {} 
}).start(); 
Scanner sc = new Scanner(hugsout); 
String rdnextline; 
while (true) { 
    rdnextline = rd.nextLine(); 
    hugsin.println(rdnextline); 
    hugsin.flush(); 
    if (rdnextline.equals("quit")) { 
     break; 
    } 
} 
System.out.println(" ... successful completion."); 
+0

ありがとう、それは働いているようだ。あなたは読者を連れて文字を読んで一度に1つずつ印刷するように見えます。キャラクターが-1でないかどうかチェックするのはなぜですか? – dinstruction

+0

'read()'は閉じられているとき-1を返します。 – saka1029

+0

そしてwhile(true)ループはユーザー入力を連続的にしか取得しません。プログラムはGHCiの出力を一度しか出力しないようですが、それはうまくループします。 – dinstruction

関連する問題