Java Runtime.getRuntime(): getting output from executing a command line program

前端 未结 12 1379
清歌不尽
清歌不尽 2020-11-22 00:18

I\'m using the runtime to run command prompt commands from my Java program. However, I\'m not aware of how I can get the output the command returns.

Here is my code:

12条回答
  •  难免孤独
    2020-11-22 00:42

    At the time of this writing, all other answers that include code may result in deadlocks.

    Processes have a limited buffer for stdout and stderr output. If you don't listen to them concurrently, one of them will fill up while you are trying reading the other. For example, you could be waiting to read from stdout while the process is waiting to write to stderr. You cannot read from the stdout buffer because it is empty and the process cannot write to the stderr buffer because it is full. You are each waiting on each other forever.

    Here is a possible way to read the output of a process without a risk of deadlocks:

    public final class Processes
    {
        private static final String NEWLINE = System.getProperty("line.separator");
    
        /**
         * @param command the command to run
         * @return the output of the command
         * @throws IOException if an I/O error occurs
         */
        public static String run(String... command) throws IOException
        {
            ProcessBuilder pb = new ProcessBuilder(command).redirectErrorStream(true);
            Process process = pb.start();
            StringBuilder result = new StringBuilder(80);
            try (BufferedReader in = new BufferedReader(new InputStreamReader(process.getInputStream())))
            {
                while (true)
                {
                    String line = in.readLine();
                    if (line == null)
                        break;
                    result.append(line).append(NEWLINE);
                }
            }
            return result.toString();
        }
    
        /**
         * Prevent construction.
         */
        private Processes()
        {
        }
    }
    

    The key is to use ProcessBuilder.redirectErrorStream(true) which will redirect stderr into the stdout stream. This allows you to read a single stream without having to alternate between stdout and stderr. If you want to implement this manually, you will have to consume the streams in two different threads to make sure you never block.

提交回复
热议问题