1

I'm trying to read the output of sam-ba.exe (which loads code to ARM microcontrollers over USB) into my Java program. 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):

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:

"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:

"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. But then why is stderr in the Java program blank?

Here is my Java code:

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.

A suggestion was made to add Redirect.INHERIT as shown, but it produces the following output. 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
  • Maybe [this](https://stackoverflow.com/questions/3936023/printing-runtime-exec-outputstream-to-console) will help? – npinti May 12 '19 at 23:04

2 Answers2

0

proc.waitFor(); This statement should appear before BufferedReader statement and its passed as in the input stream reader. Note: Process.waitFor() method to pause the current thread until your process has had an opportunity to complete. Then using BufferReader you can read the output.

Ref : Capture the output of an external program in JAVA

Senthil
  • 2,156
  • 1
  • 14
  • 19
0

Issue seems to be the command which you pass, when i use mysqld start in the process command line args of your program. I am able to see the ouptut. So issue is with the CLI command you are passing. 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
Senthil
  • 2,156
  • 1
  • 14
  • 19
  • I can run the sam-ba.exe file manually in the command prompt, and it prints "Error: no serial ports found" (see first part of my post). But if I replace the sam-ba command in my java code with just a plain "ping", the normal ping output gets printed first, before the input and error stream, but when the inputStream and errorStream are supposed to print, it is still empty (it is exactly the same as the last part of my post but with the respective output). – Judd Foster May 13 '19 at 01:51
  • If I comment out the lines with "Redirect.INHERIT" in them, ping now works as expected, with the output printing under the standard input section. So it is something to do with the sam-ba command. How can it output to the terminal if it's not going through the error or input stream? – Judd Foster May 13 '19 at 02:23