user903772
user903772

Reputation: 1562

Java issue command in command prompt

I have the following class file. This start a command prompt and print the responses. weird thing is after the first print i.e. dir the subsequent doesn't print. Please advice.

import java.io.*;
public class JavaApplication14 {
static Process p;

public static void main(String[] args) {
    try {
        String line;

        p = Runtime.getRuntime().exec("cmd.exe");
        OutputStream stdin = p.getOutputStream();
        InputStream stderr = p.getErrorStream();
        InputStream stdout = p.getInputStream();

        BufferedReader reader = new BufferedReader(new InputStreamReader(stdout));
        BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(stdin));

        String input = "dir";
        input += "\n";
        writer.write(input);
        writer.flush();



        while ((line = reader.readLine()) != null) {
            System.out.println("Stdout: " + line);
        }
         input = "cd..";
        input += "\n";
        writer.write(input);
        writer.flush();
        input = "dir";
        input += "\n";
        writer.write(input);
        writer.close();

        while ((line = reader.readLine()) != null) {
            System.out.println("Stdout: " + line);
        }
    } catch (IOException ex) {
        Logger.getLogger(JavaApplication14.class.getName()).log(Level.SEVERE, null, ex);
    }
 }
 }

Upvotes: 2

Views: 167

Answers (2)

Marko Topolnik
Marko Topolnik

Reputation: 200158

You are trying to do fundamentally asynchronous work from just one thread, using synchronous I/O operations. Your approach is bound to fail.

Specifically, readLine() blocks until there is a full line to be read, or until the underlying stream is closed.

You'll have to write quite a bit more code, involving threads, to make this work. This is a pain point in Java.

You could also use the ProcessBuilder, especially its redirectOutput method with the argument value INHERIT, to make the subprocess inherit your main process's stdout. In this scenario you won't have the opportunity to analyze the subprocess's output in Java.

Upvotes: 2

Andreas Fester
Andreas Fester

Reputation: 36630

Your (first) while() loop never terminates:

while ((line = reader.readLine()) != null) {
    System.out.println("Stdout: " + line);
}

readLine() returns null when the stream is closed, but since your sub process is still running, the stream never gets closed.

To solve this, you can either move the reading part into a separate thread (which requires additional synchronization), or a simpler solution would be to see if a specific line contents is read, for example if the command line prompt was printed by cmd.exe:

while ( !(line = reader.readLine()).startsWith("C:\\") ) {
    System.out.println("Stdout: " + line);
}

This should work for your particular use case, and might be sufficient to do some learning - for real applications, you might want to have a look into the Apache Commons Exec project.

Upvotes: 4

Related Questions