Java program using ProcessBuilder with input and output streams does not work

I've looked at similar questions here on Stack Overflow, however, I can't seem to make this work.

I have a Java program that needs to use ProcessBuilder to load a C executable. The file just takes a string through the CLI and converts it to uppercase. The java program creates a system process with ProcessBuilder to manage this executable and must send the string and receive the converted one to print it to the CLI.

This is the code for uppercases.c :

#include <stdio.h>

int main(int argc, char *argv[]) {
    char text[1024];
    scanf("%s", &text[0]);

    int i;
    for(i = 0; i < strlen(text); i++) {
        text[i] = toupper(text[i]);
    }

    printf("%s\n", text);
    return 0;
}

      

I compiled it with

$ gcc uppercases.c -o uppercases

      

And launched it with

$ ./uppercases

      

Everything works perfectly. Now this is the code for Uppercase.java . I need to create an OutputStream to send a string to the C executable (uppercases) and then I create an InputStream to save its output and print it to the CLI:

public class Uppercase {

public static void main(String[] command) {
    String textIn, textOut;
    Scanner reader = new Scanner(System.in);

    // This is what we want to send
    System.out.println("Write something: ");
    textIn = reader.nextLine();

    try {
        // Here I create a process to handle "uppercases"
        Process process = new ProcessBuilder(command).start();

        OutputStream os = process.getOutputStream();
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(os));

        // According to me, this will send the string to "uppercases"
        bw.write(textIn);
        bw.flush();

        // This is to read the output of "uppercases"
        InputStream is = process.getInputStream();
        BufferedReader br = new BufferedReader (new InputStreamReader(is));

        while ((textOut = br.readLine()) != null) {
             System.out.println(textOut);
        }

        os.close();
        is.close();

    } catch (IOException e) {
        System.out.println("I/O error:" + e.getMessage());
    } catch (Exception e) {
        System.out.println("Error:" + e.getMessage());
    }
  }
}

      

To compile, I type:

$ javac Uppercase.java

      

And execute:

$ java Uppercase ./uppercases

      

The problem is that when I type a line and press Enter, the cursor stays there forever, I enter enter again and nothing happens, and finally I need to press CTRL + C to exit. Any help would be appreciated.

+3


source to share


1 answer


Everything works fine with your java program with one exception: you are using BufferedWriter

which you clean up correctly, but since the line you are writing does not contain a newline, the C program is still expecting more input.

If you write:

// According to me, this will send the string to "uppercases"
bw.write(textIn);
bw.write("\n");
bw.flush();

      

Enough and the program exits normally.



But if you really want things to be bulletproof, you should close bw

to clearly indicate the subprocess shouldn't wait for more input:

// According to me, this will send the string to "uppercases"
bw.write(textIn);
bw.close();

      

Then the program ends normally (and correctly) even without a newline ending. Of course, in this case, the latter is os.close()

no longer needed, but it is still harmless.

+2


source







All Articles