2017-04-23 16 views
0

私のJavaプログラムがCプログラムと通信したい。これは単なる例ですが、私はそれを働かせることはできません。 Javaプログラムは、Cプログラムを実行し、その入力ストリームに書き込むことになっています。 Cプログラムはこれを見て、応答としてstdoutに書き込むべきです。最後に、Javaプログラムはこの応答をCプログラムのstdoutから読み込み、それを画面に出力する必要があります。Javaからstdin/outを使ってCプログラムと通信する

コマンドラインからCプログラムを実行すると、目的の動作が得られます。しかし、Javaプログラムから実行すると、単に「ハング」して何もしません。 JavaプログラムはCプログラムの標準にメッセージを書き込んだようですが、このメッセージはCプログラムには表示されません。

私は、メッセージを読むだけでメッセージを読むようにCプログラムを設定し、メッセージを読むことを確認します。ここで

は、Cプログラムである:

#include <stdio.h> 
#include <string.h> 

void hello(); 
void wrong(); 

int main() { 
    char buff[256]; 

    /* 1. read stdin */ 
    fscanf(stdin, "%s", buff); 

    /* side effect - if message was received it should be 
     printed to file */ 
    FILE *fp = fopen("file.txt", "w"); 
    fprintf(fp, "%s", buff); 
    fclose(fp); 

    /* 2. depending on message, write something to stdout */ 
    if(strcmp(buff, "hello") == 0) { 
     hello(); 
    } else { 
     wrong(); 
    } 
} 

void hello() { 
    printf("Hello World!"); 
} 

void wrong() { 
    printf("WRONG!"); 
} 

そしてここでは、Javaプログラムです:

import java.io.*; 

public class Main { 
    public static void main(String[] args) { 
     try { 
      // 1. run C program 
      Process proc = Runtime.getRuntime().exec("./hello"); 
      InputStream in = proc.getInputStream(); 
      OutputStream out = proc.getOutputStream(); 
      // 2. write 'hello' to 'hello' program 
      writeToProc(out, "hello"); 
      // 3. read response 
      readFromProc(in); 
     } catch(Exception e) { 
      e.printStackTrace(); 
     } 
    } 

    // write message to process 
    public static void writeToProc(OutputStream out, String msg) throws IOException { 
     byte[] buff = msg.getBytes(); 
     out.write(buff); 
     out.flush(); 
     System.out.println("done writing: " + new String(buff)); 
    } 

    // read stdin of process 
    public static void readFromProc(InputStream in) throws IOException { 
     byte[] buff = new byte[256]; 
     int read = in.read(); 
     for(int i=0; read != -1; i++) { 
      read = in.read(); 
      buff[i] = (byte) read; 
     } 
     String str = new String(buff); 
     System.out.println("proc says: " + str); 
    } 
} 

私はメインを実行すると、私は次の出力を得る:その後、

$ java Main 
    done writing: hello 

をと単に点滅するカーソルとファイル "file.txt"は書き込まれず、Cプログラムがstdinから "hello"を読み込まなかったことを示します。

これは簡単な例ですので、私は何か単純なものが見つからないか、何とか間違った方法でやって来ると思います。

+1

まず、CプログラムまたはJavaプログラムの問題はありますか?次に、動作しているタグとコードを取り除きます。 –

+0

私は分かりません。私はJavaプログラムを推測していますが、わかりません。 – Yulek

+0

さて、これから始めましょう:JavaプログラムがCプログラムを呼び出すのであれば、Cプログラムは動作しますか? –

答えて

3

問題は、あなたがfscanf"press enter"にプロセスを無限に待ち続けるので、Javaから送信された文字列に改行文字\nを(空白はトリックを行う必要があります)を追加するのを忘れたということです。私はコードにいくつかの変更を加えました。変更はコメントに記録されています。

import java.io.IOException; 
import java.io.InputStream; 
import java.io.OutputStream; 

public class Main { 
    public static void main(String[] args) { 
     try { 
      // 1. run C program 
      Process proc = Runtime.getRuntime().exec("./hello"); 
      InputStream in = proc.getInputStream(); 
      OutputStream out = proc.getOutputStream(); 
      // 2. write 'hello' to 'hello' program 
      // <change> 
      // don't forget to add the new line here or in the 
      // writeToProc method 
      writeToProc(out, "hello\n"); 
      // 3. read response 
      readFromProc(in); 
     } catch(Exception e) { 
      e.printStackTrace(); 
     } 
    } 

    // write message to process 
    public static void writeToProc(OutputStream out, String msg) throws IOException { 
     // <change> 
     // Using UTF-8 encoding since all chars in C are byte sized 
     byte[] buff = msg.getBytes("UTF-8"); 
     out.write(buff); 
     out.flush(); 
     System.out.println("done writing: " + new String(buff)); 
    } 

    // read stdin of process 
    public static void readFromProc(InputStream in) throws IOException { 
     byte[] buff = new byte[256]; 
     int read = in.read(); 
     int index = 0; 
     while(read != -1) { 
      buff[index] = (byte) read; 
      read = in.read(); 
      ++index; 
     } 
     String str = new String(buff, 0, index); 
     System.out.println("proc says: " + str); 
    } 
} 
+0

'new String(buff、0、index)'を使用してバッファの有効部分のみを変換する場合、配列コピーは必要ありません。 (また、残りの要素には、Unicodeを含むASCII互換コードで0x30 aka 48である 'char' 0 'ではなく、表示時に見えない' byte '値0が含まれています)。 –

+0

@ dave_thompson_085あなたの入力に感謝しました。 'new String(buff、0、index)'コンストラクタを考えてください。後ろのゼロについては、私は彼らも見えないだろうと思ったけど、彼らは日食で現れた、私は彼らが "本当の"コンソールに表示されないかもしれないと思うが、それを試していない。私は 'new String(buff、0、index)'ソリューションが好きで、そのアプローチを使うための私の答えを更新しました。ありがとう! – StaticBeagle

関連する問題