1

i have a program that creates a process with ProcessBuilder and executes an external program (.jar). The external process should receive a String from stdin, convert their characters to lower or upper case and send the converted String thru stdout. The main process reads the String from keyboard, sends it to the external process using a stream and prints the output of the external process. But when i run the main program it seems that it gets stuck with the external process trying to read data from its stdin. How can i fix this, any suggestions? There's another way to accomplish this (sending the String as an argument of the command that executes the external program) but i need to do it using streams.

Here is the code of main program:

public static void main(String[] args) throws IOException {
    String str = JOptionPane.showInputDialog("Insert a String");

    String[] cmd = {"java", "-jar", 
    "ejecutable/Transformador2.jar"};

    Process process = new ProcessBuilder(cmd).start();
    InputStream is = process.getInputStream();
    InputStreamReader isr = new InputStreamReader(is);
    BufferedReader br = new BufferedReader(isr);

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

    bw.write(str);

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

And here is the code of the external process:

public static void main(String[] args) throws IOException {
    String str, strConv="";
    BufferedReader input = new BufferedReader(new InputStreamReader(System.in));
    char c;

    str = input.readLine();

    for (int i=0; i<str.length(); i++) {

        c = str.charAt(i);

        if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) {
            if (c == Character.toUpperCase(c))
                strConv += Character.toLowerCase(c);
            else if (c == Character.toLowerCase(c))
                strConv += Character.toUpperCase(c);
        }

    }

    System.out.print(strConv);

}

Thanks in advance.

NetrunnerX
  • 41
  • 6
  • I'm in no way sure of this, but it's possible that when you check whether the output is null, the other process hasn't printed anything out *yet*, because it's not ready yet, but the original program exits because the while loop ends. Again, this is just a wild guess. – Benjamin Sigal Sep 30 '16 at 14:35
  • You must either create a Thread to send the input, or create a Thread to read the output. There is no way to do this without creating a Thread. – VGR Sep 30 '16 at 14:37
  • [This post](http://stackoverflow.com/questions/18903549/writing-to-inputstream-of-a-java-process) could be useful. – D.B. Sep 30 '16 at 14:40
  • Try bw.flush() after the write – David Zimmerman Sep 30 '16 at 14:53
  • @DavidZimmerman I tried bw.flush() but didn't work. – NetrunnerX Sep 30 '16 at 15:59
  • @VGR i tried with threads, it didn't work. – NetrunnerX Sep 30 '16 at 17:08
  • 1
    @D.B. I solved the problem. Thanks for the link, was really useful. I have to close the outputstream after writing the string, then it works :) br.write(str); br.close(); – NetrunnerX Sep 30 '16 at 17:21
  • 1
    @NetrunnerX Instead of editing the solution into your post, you can and should post an answer to your own question below – nbrooks Sep 30 '16 at 17:47
  • @nbrooks thanks for the advice, i'll do it. – NetrunnerX Sep 30 '16 at 17:50

2 Answers2

0

SOLVED: The ouput stream needs to be closed after the string is sent to the external process.

bw.write(str);
bw.close();
NetrunnerX
  • 41
  • 6
0

To be exact, you need to bw.flush() to push the data from the buffer to underlying stream. bw.close() implicitly flushes the buffer. That is why it is working.

Antoniossss
  • 31,590
  • 6
  • 57
  • 99
  • That's good to know, although if i try only with bw.flush() sentence, the code don't work. So we can say that closing the buffer after flushing it is also necessary. Thanks for the answer. – NetrunnerX Oct 01 '16 at 11:12
  • You should ALWAYS close the streams to prevent resource leaks. Close flushes the stream. In this particular case, you area using `BufferedReader` for input read. So, untill the data quantity will not overflow the input buffer `readlLine` will bock untill then, or line terminator char will be detected, or until stream closes - this is a signal that no more data will come thus buffer can be emtpied and its value is returned by `readLine`. If you would send significant ammount of data, it would also work without closing the stream. *The default buffer size is 8192 characters* – Antoniossss Oct 03 '16 at 07:53