Books
in black and white
Main menu
Share a book About us Home
Books
Biology Business Chemistry Computers Culture Economics Fiction Games Guide History Management Mathematical Medicine Mental Fitnes Physics Psychology Scince Sport Technics
Ads

More Java Pitfalls Share Reactor - Daconta M,C.

Daconta M,C. More Java Pitfalls Share Reactor - Wiley publishing, 2003. - 476 p.
ISBN: 0-471-23751-5
Download (direct link): morejavapitfallssharereactor2003.pdf
Previous << 1 .. 5 6 7 8 9 10 < 11 > 12 13 14 15 16 17 .. 166 >> Next

01 package org.javapitfalls.item1;
02
03 import java.util.*;
04 import java.io.*;
05
// StreamGobbler removed for brevity
32
33 public class BadWinRedirect
34 {
35 public static void main(String args[])
36 {
37 try
38 {
39 Runtime rt = Runtime.getRuntime();
40 Process proc = rt.execi "java jecho 'Hello World' > test.txt"); 2
// remaining code same as GoodWindowsExec.java
63 }
Listing 1.5 BadWinRedirect.java
Running BadWinRedirect produces:
E:\classes\org\javapitfalls\Item1>java 2
org.javapitfalls.Item1.BadWinRedirect
OUTPUT>'Hello World' > test.txt
ExitValue: 0
The program BadWinRedirect attempted to redirect the output of a simple Java version of an echo program into the file test.txt. Unfortunately, when we check to see if the file test.txt is created, we find that it does not exist. The jecho program simply takes its command-line arguments and writes them to the standard output stream. The source for jecho is available on the Web site. The user assumed you could redirect standard output into a file just like you do on a DOS command line. Unfortunately, that is not the way you redirect the output. The incorrect assumption here is that the exec() method acts like a shell interpreter, and it does not. The exec() method executes a single executable (a program or script). If you want to process the stream to either redirect it or pipe it into another program, you must do that programmatically using the java.io package. Listing 1.6 properly redirects the standard output stream of the jecho process into a file.
When Runtime.exec() Won't 13
01 package org.javapitfalls.item1;
02
03 import java.util.*;
04 import java.io.*;
05
06 class StreamGobbler extends Thread
07 {
08 InputStream is;
09 String type;
10 OutputStream os;
11
12 StreamGobbler(InputStream is, String type)
13 {
14 this(is, type, null);
15 }
16
17 StreamGobbler(InputStream is, String type, OutputStream 2
redirect)
18 {
19 this.is = is;
20 this.type = type;
21 this.os = redirect;
22 }
23
24 public void run()
25 {
26: try
27 {
28 PrintWriter pw = null;
29 if (os != null)
30 pw = new PrintWriter(os);
31
32 InputStreamReader isr = new InputStreamReader(is);
33 BufferedReader br = new BufferedReader(isr);
34 String line=null;
35 while ( (line = br.readLine()) != null)
36 {
37 if (pw != null)
38 {
39 pw.println(line);
40 pw.flush();
41 }
42 System.out.println(type + ">" + line);
43 }
44 if (pw != null)
45 pw.flush();
46 } catch (IOException ioe)
Listing 1.6 GoodWinRedirect.java (continued)
14 Item 1
47 {
48 ioe.printStackTrace();
49 }
50 }
51 }
52
53 public class GoodWinRedirect
54 {
55 public static void main(String args[])
56 {
// command argument check omitted for brevity ...
62
63 try
64 {
65 FileOutputStream fos = new File0utputStream(args[0]);
66 Runtime rt = Runtime.getRuntime();
67 Process proc = rt.exec("java jecho 'Hello World'”);
68 // any error message?
69 StreamGobbler errorGobbler = new
70 StreamGobbler(proc.getErrorStream(), "ERROR”);
71
72 // any output?
73 StreamGobbler outputGobbler = new
74 StreamGobbler(proc.getInputStream(), "OUTPUT", fos);
75
76 // kick them off
77 errorGobbler.start();
78 outputGobbler.start();
79
80 // any error???
81 int exitVal = proc.waitFor();
82 System.out.println("ExitValue: " + exitVal);
83 fos.flush();
84 fos.close();
85 } catch (Throwable t)
86 {
87 t.printStackTrace();
88 }
89 }
90 }
Listing 1.6 (continued)
When Runtime.exec() Won't 15
Running GoodWinRedirect produces
E:\classes\org\javapitfalls\item1>java 2
org.javapitfalls.item1.GoodWinRedirect test.txt
OUTPUT>'Hello World'
ExitValue: 0
After running GoodWinRedirect, we find that test.txt does exist. The solution to the pitfall was to simply handle the redirection by handling the standard output stream of the external process separate from the Runtime.exec() method. We create a separate OutputStream, read in the filename to redirect the output to, open the file, and write the output we receive from the standard output of the spawned process to the file. In Listing 1.7 this is accomplished by adding a new constructor to our Stream-Gobbler class. The new constructor takes three arguments: the input stream to gobble, the type String, which labels the stream we are gobbling, and lastly the output stream to redirect the input to. This new version of StreamGobbler does not break any of the previous code it was used in, since we have not changed the existing public API (just extended it). A reader of the JavaWorld article, George Neervoort, noted an important improvement to GoodWinRedirect is to ensure that the streams have completed reading input from the process. This is necessary because it is possible for the process to end before the threads have completed. Here is his solution to that problem (thanks George!):
Previous << 1 .. 5 6 7 8 9 10 < 11 > 12 13 14 15 16 17 .. 166 >> Next