问题
I want my Java program to communicate with a C program. This is just a simple example but I can't get it working. The Java program is supposed to run the C program and write to its input stream. The C program should see this and write to stdout in response. Finally, the Java program should read this response from the C program's stdout and print it to the screen.
Running the C program from command line I get the desired behaviour. However, when ran from the Java program, it just "hangs" and doesn't do anything. The Java program seems to have written its message to C program's stdin, but this message isn't seen in the C program.
I set the C program to write the message it reads to file just to check that it does read the message, and it doesn't do that.
Here is the C program:
#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!");
}
And here's the Java program:
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);
}
}
When I run Main, I get the following output:
$ java Main
done writing: hello
And then just a blinking cursor and file "file.txt" is not written, indicating that the C program didn't read "hello" from stdin.
This is a simple example so I guess I'm missing something simple or coming at this the wrong way somehow.
回答1:
The problem is that you forgot to add the new line character \n
to the string that you are sending from Java thus fscanf
keeps waiting indefinitely for the process to "press enter"
. I've made some modifications to the code and the changes are documented in comments.
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);
}
}
来源:https://stackoverflow.com/questions/43577359/communicate-with-c-program-using-stdin-out-from-java