Running Commands and Getting Output From Them

This section explains how to execute a program from Java and read the output of that program back into your application. Just as a reminder, the use of OS commands in your code destroys portability.

If you can live with that limitation, there are four general steps to executing a program from your Java program.

  1. Get the object representing the current run-time environment. A static method in class java.lang.Runtime does this.

  2. Call the exec method in the run-time object, with your command as an argument string. Give the full path name to the executable, and make sure the executable really exists on the system. The call to exec() returns a Process object.

  3. Connect the output of the Process (which will be coming to you as an input stream) to an input stream reader in your program.

  4. You can either read individual characters from the input stream, or layer a BufferedReader on it and read a line at a time as in the code below.

Many books use the example of getting a list of files in a directory, even though there is already a Java method to do that in class File. The following code in class java.io.File will return an array of Strings, one string for each file name in the directory:

File f = new File(".");
String myFiles[] = f.list();

The file with the special name of “.” is used on many operating systems to refer to the current working directory. We will use a different example here. We will execute a command in our Java program to make a file read-only. On Linux or other Unix, the command used would be “/bin/chmod a-w“, on Windows we use the “attrib +R” command as shown in the following code.

Executing the attrib command from Java

import java.io.*;
public class ReadOnly {
    public static void main(String args[]) {
        try {
          Runtime rt = Runtime.getRuntime();  // step 1
          String cmd =
             // pathname changes in different versions of windows
             // "c:\windows\command\attrib.exe  +R " + args[0]; // Win98
                "c:\windows\system32\attrib.exe  +R " + args[0];  // WinXP
          Process prcs = rt.exec(cmd);        // step 2
          InputStreamReader isr =                 // step 3
             new InputStreamReader( prcs.getInputStream() );
          BufferedReader in =
             new BufferedReader( isr );         // step 4.
          String line;
          System.out.printf("have set %s to read-only %n", args[0]);
          while (in.ready()) {
             System.out.println(in.readLine());
          }
          // Clean up
          prcs.waitFor();
          in.close();
        } catch(Exception e) { System.out.println(e); }
     }
}

This program uses the class java.lang.Runtime, which does several run-time-related things. The main use is to provide a way to execute other programs, but it can also load classes, request garbage collection, and do other memory-related things. It's a bit of a “grab-bag” for things that are done by the JVM.

The exec() method returns an object of class Process. That object allows you to get the in, out, and err streams from a process, and to wait for it to complete. You'll often see the lines of code reduced by directly wrapping the classes on each other, like this:

prcs = Runtime.getRuntime().exec(cmd);
in = new BufferedReader(
      new InputStreamReader( prcs.getInputStream()));

That replaces the lines commented as Steps 1, 2, 3, and 4 in the example. The attrib program that we have executed here doesn't produce any output, but we show how you can read lines from the InputStream for programs that do produce output. The waitFor() method lets the native program complete before the Java program continues on.

You can run the program and check the results with:

c: javac ReadOnly.java
c: java ReadOnly somefile
have set to read-only
c: dir /ar

 Volume in drive C has no label
 Volume Serial Number is 0D2B-14DC
 Directory of C:JJ4ch14io

SOMEFILE                6 08-24-01 7:56a somefile
         1 file(s)          6 bytes
         0 dir(s)     978.20 MB free

The “ar” option tells “dir” to only show files with the read-only attribute.

Note that there are half a dozen other versions of the Runtime.exec() method taking different arguments. These arguments can specify environment variables and the new working directory for the subprocess. Please refer to the API guide for the full list.

Limitations on running processes

An untrusted applet (Java program on a web page that is downloaded and run inside your browser when you visit that Web page) does not have permission to run executables. The Runtime.exec methods do not work well for special processes such as native windowing processes, daemon processes, Win16 or DOS processes on Win32, or shell scripts. In other words, many of the most useful things don't work! You can expect it to run a non-graphics program and that's about it. There are other problems, too:

  • Most platforms provide limited buffer size for standard input and output streams. It might be as small as 1 or 2 Kbytes! If you do not promptly write to the input stream and read from the output stream of the subprocess, you may cause that subprocess to block and even deadlock. The same problem is often seen with Piped I/O, and it seems like everyone has to find out this limitation the hard way.

  • The created subprocess is not started in an interactive shell, and so it does not have its own terminal or console. All its standard I/O (i.e., in, out, error) will take place to/from the parent process. The parent process uses the three streams (Process.getOutputStream(), Process.getInputStream(), Process.getErrorStream()) to feed input to and get output from the subprocess.

  • Another implication of not running the program in an interactive shell is that the exec method does not have the ability to look for executables in the search path that your shell (or command interpreter) knows about. You should provide the complete path name for the command. This also means you cannot use commands that are built into a shell unless you explicitly call a shell as the program you wish to run (DIR and DEL are two Windows commands that are actually implemented by the shell). On Windows you can do a “find” for files with a “.exe” suffix to see which programs you can run.

  • You will only be able to communicate with programs that use standard in, out, and err. Some programs like xterm open a new tty, or a GUI. These programs cannot be used as you would wish.

When you add all these restrictions together, plus the fact that a program that invokes an OS command or other program is usually not portable, the usefulness of the approach can be quite limited.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.16.76.138