简体   繁体   English

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

[英]Unable to read program output using both STDIN and STDERR in Java

I'm trying to read the output of sam-ba.exe (which loads code to ARM microcontrollers over USB) into my Java program. 我正在尝试将sam-ba.exe(通过USB将代码加载到ARM微控制器的代码)的输出读取到Java程序中。 When writing this exact command in command prompt: 在命令提示符下编写此确切命令时:

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

The result is: 结果是:

Error: No serial ports found

But when executing this command in the following Java code, nothing is returned from either the standard output or standard error streams (see the following): 但是,在以下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):

What makes it more annoying is that substituting this command in the Java code wil return information in the stderr stream: 更令人讨厌的是,将以下命令替换为Java代码将在stderr流中返回信息:

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

The result: 结果:

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>.

In the console, I tried redirecting the output of the first (non-working) command to a text file, and the text file displays the expected Error no serial ports, but only if the following command is used: 在控制台中,我尝试将第一个(无效)命令的输出重定向到文本文件,并且该文本文件仅在使用以下命令的情况下显示预期的Error no serial port:

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

This leads me to believe that the message is coming from stderr because if I omit the "2>&1", the text file is blank. 这使我相信该消息来自stderr,因为如果我省略“ 2>&1”,则文本文件为空。 But then why is stderr in the Java program blank? 但是,为什么Java程序中的stderr空白?

Here is my Java code: 这是我的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();
        }
    }
}

Any help would be great, 任何帮助都会很棒,

Judd 贾德

Update: As suggested I am now using ProcessBuilder and removed the quotes, but the result is exactly the same. 更新:按照建议,我现在使用ProcessBuilder并删除了引号,但结果完全相同。

A suggestion was made to add Redirect.INHERIT as shown, but it produces the following output. 建议添加如图所示的Redirect.INHERIT ,但是会产生以下输出。 It looks like it just bypasses the input streams and goes straight to the terminal? 看起来它只是绕过输入流并直接进入终端?

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();
        }
    }
}

Output: 输出:

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

proc.waitFor(); proc.waitFor(); This statement should appear before BufferedReader statement and its passed as in the input stream reader. 该语句应出现在BufferedReader语句之前,并在输入流阅读器中按原样传递。 Note: Process.waitFor() method to pause the current thread until your process has had an opportunity to complete. 注意:Process.waitFor()方法暂停当前线程,直到您的进程有机会完成。 Then using BufferReader you can read the output. 然后,使用BufferReader可以读取输出。

Ref : Capture the output of an external program in JAVA 参考: 在JAVA中捕获外部程序的输出

Issue seems to be the command which you pass, when i use mysqld start in the process command line args of your program. 当我在程序的进程命令行args中使用mysqld start时,问题似乎是您传递的命令。 I am able to see the ouptut. 我能够看到输出。 So issue is with the CLI command you are passing. 所以问题在于您传递的CLI命令。 Suggestion Manually run it and see the output printed. 建议手动运行它,然后查看输出结果。

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

Sample Output : 样本输出:

    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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM