无法在Java中同时使用STDIN和STDERR读取程序输出

时间:2019-05-12 21:45:40

标签: java inputstream

我正在尝试将sam-ba.exe的输出(通过USB将代码加载到ARM微控制器)读入Java程序。在命令提示符下编写此确切命令时:

"sam-ba_3.2.1\sam-ba.exe" -p usb -d SAME70 -a internalflash

结果是:

Error: No serial ports found

但是在以下Java代码中执行此命令时,标准输出或标准错误流均不返回任何内容(请参见以下内容):

Command executed: "sam-ba_3.2.1\sam-ba.exe" -p usb -d SAME70 -a internalflash
Here is the standard output of the command:

Here is the standard error of the command (if any):

更令人讨厌的是,用Java代码替换此命令将在stderr流中返回信息:

"sam-ba_3.2.1\sam-ba.exe" --help

结果:

Here is the standard output of the command:

Here is the standard error of the command (if any):

SAM-BA Command Line Tool v3.2.1
Copyright 2015-2017 ATMEL Corporation

Usage: sam-ba_3.2.1\sam-ba.exe [options]

Options:
  -v, --version                          Displays version information.
  -h, --help                             Displays this help.
  -t, --tracelevel <trace_level>         Set trace level to <trace_level>.
  -x, --execute <script.qml>             Execute script <script-file>.
  -p, --port <port[:options:...]>        Communicate with device using <port>.
  -d, --device <device[:options:...]>    Connected device is <device>.
  -b, --board <board[:options:...]>      Connected board is <board>.
  -m, --monitor <command[:options:...]>  Run monitor command <command>.
  -a, --applet <applet[:options:...]>    Load and initialize applet <applet>.
  -c, --command <command[:args:...]>     Run command <command>.

在控制台中,我尝试将第一个(非工作)命令的输出重定向到文本文件,并且该文本文件显示预期的错误,无串行端口,但仅在使用以下命令时显示:

"sam-ba_3.2.1\sam-ba.exe" -p usb -d SAME70 -a internalflash > output.txt 2>&1

这使我相信该消息来自stderr,因为如果我省略“ 2>&1”,则文本文件为空白。但是,为什么Java程序中的stderr空白?

这是我的Java代码:

import java.io.IOException;
import java.io.InputStreamReader;
import java.io.InputStream;
import java.io.BufferedReader;

public class ProcessDemo {

   public static void main(String[] args) {
        try
        {
            Runtime r = Runtime.getRuntime();
            //String command = "\"sam-ba_3.2.1\\sam-ba.exe\" --help";
            String command = "\"sam-ba_3.2.1\\sam-ba.exe\" -p usb -d SAME70 -a internalflash";

            System.out.println("Command executed: " + command);

            Process proc = r.exec(command);

            BufferedReader stdInput = new BufferedReader(new InputStreamReader(proc.getInputStream()));
            BufferedReader stdError = new BufferedReader(new InputStreamReader(proc.getErrorStream()));

            // read the output from the command
            System.out.println("Here is the standard output of the command:\n");
            String s = null;
            while ((s = stdInput.readLine()) != null) {
                System.out.println(s);
            }

            // read any errors from the attempted command
            System.out.println("Here is the standard error of the command (if any):\n");

            while ((s = stdError.readLine()) != null) {
                System.out.println(s);
            }
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
    }
}

任何帮助都会很棒,

贾德

更新:如建议的那样,我现在使用ProcessBuilder并删除了引号,但结果完全相同。

有人建议添加Redirect.INHERIT,如图所示,但会产生以下输出。看起来它只是绕过输入流而直接进入终端?

import java.io.IOException;
import java.io.InputStreamReader;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.BufferedReader;


public class ProcessDemo {

   public static void main(String[] args) {

        try
        {
            // String[] command = {"sam-ba_3.2.1\\sam-ba.exe","--help"};
            String[] command = {"sam-ba_3.2.1\\sam-ba.exe", "-p", "usb", "-d", "SAME70", "-a", "internalflash", "-c", "write:\"GCCBoardProject1.bin\""};
            ProcessBuilder pb = new ProcessBuilder(command);
            pb.redirectOutput(ProcessBuilder.Redirect.INHERIT);
            pb.redirectError(ProcessBuilder.Redirect.INHERIT);

            Process proc = pb.start();
            proc.waitFor();

            BufferedReader stdInput = new BufferedReader(new InputStreamReader(proc.getInputStream()));
            BufferedReader stdError = new BufferedReader(new InputStreamReader(proc.getErrorStream()));

            System.out.println("Here is the standard output of the command:\n");

            // read the output from the command
            String s = null;
            while ((s = stdInput.readLine()) != null)
            {
                System.out.println(s);
            }

            // read any errors from the attempted command
            System.out.println("Here is the standard error of the command (if any):\n");

            while ((s = stdError.readLine()) != null)
            {
                System.out.println(s);
            }

            System.out.println("return value: " + proc.exitValue());
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
    }
}

输出:

Error: No serial ports found
Here is the standard output of the command:

Here is the standard error of the command (if any):

return value: -1

2 个答案:

答案 0 :(得分:0)

proc.waitFor();该语句应出现在BufferedReader语句之前,并在输入流阅读器中按原样传递。注意:Process.waitFor()方法暂停当前线程,直到您的进程有机会完成。然后,使用BufferReader可以读取输出。

Ref:Capture the output of an external program in JAVA

答案 1 :(得分:0)

当我在程序的进程命令行args中使用mysqld start时,问题似乎是您传递的命令。我能够看到输出。所以问题在于您传递的CLI命令。建议手动运行它,然后查看输出结果。

String[] command = {"C:\\Users\\userid\\Downloads\\mysql-5.7.13-winx64\\mysql-5.7.13-winx64\\bin\\mysqld.exe", "--console"};  

样本输出:

    C:\Users\userid\other\stk-overflow>java ProcessDemo



   2019-05-13T00:57:04.191518Z 0 [Warning] TIMESTAMP with implicit DEFAULT value is deprecated. Please use --explicit_defaults_for_timestamp server option (see documentation for more details).
    2019-05-13T00:57:04.191518Z 0 [Warning] 'NO_AUTO_CREATE_USER' sql mode was not set.
    2019-05-13T00:57:04.191518Z 0 [Warning] Insecure configuration for --secure-file-priv: Current value does not restrict location of generated files. Consider setting it to a valid, non-empty path.
    2019-05-13T00:57:04.191518Z 0 [Note] C:\Users\userid\Downloads\mysql-5.7.13-winx64\mysql-5.7.13-winx64\bin\mysqld.exe (mysqld 5.7.13) starting as process 21604 ...
    2019-05-13T00:57:04.201520Z 0 [Note] InnoDB: Mutexes and rw_locks use Windows interlocked functions
    2019-05-13T00:57:04.202742Z 0 [Note] InnoDB: Uses event mutexes
    2019-05-13T00:57:04.203516Z 0 [Note] InnoDB: _mm_lfence() and _mm_sfence() are used for memory barrier
    2019-05-13T00:57:04.203516Z 0 [Note] InnoDB: Compressed tables use zlib 1.2.3
    2019-05-13T00:57:04.204517Z 0 [Note] InnoDB: Number of pools: 1
    2019-05-13T00:57:04.205519Z 0 [Note] InnoDB: Not using CPU crc32 instructions
    2019-05-13T00:57:04.209518Z 0 [Note] InnoDB: Initializing buffer pool, total size = 128M, instances = 1, chunk size = 128M