The Console: System.out, System.in, and System.err

The console is the default destination for output written to System.out or System.err and the default source of input for System.in . On most platforms the console is the command-line environment from which the Java program was initially launched, perhaps an xterm (Figure 1.1) or a DOS shell window (Figure 1.2). The word console is something of a misnomer, since on Unix systems the console refers to a very specific command-line shell, rather than being a generic term for command-line shells overall.

An xterm console on Unix

Figure 1-1. An xterm console on Unix

A DOS shell console on Windows NT

Figure 1-2. A DOS shell console on Windows NT

Many common misconceptions about I/O occur because most programmers’ first exposure to I/O is through the console. The console is convenient for quick hacks and toy examples commonly found in textbooks, and I will use it for that in this book, but it’s really a very unusual source of input and destination for output, and good Java programs avoid it. It behaves almost, but not completely, unlike anything else you’d want to read from or write to. While consoles make convenient examples in programming texts like this one, they’re a horrible user interface and really have little place in modern programs. Users are more comfortable with a well-defined graphical user interface. Furthermore, the console is unreliable across platforms. The Mac, for example, has no native console. Macintosh Runtime for Java 2 and earlier has a console window that works only for output, but not for input; that is, System.out works but System.in does not.[4] Figure 1.3 shows the Mac console window.

The Mac console, used exclusively by Java programs

Figure 1-3. The Mac console, used exclusively by Java programs

Personal Digital Assistants (PDAs) and other handheld devices running PersonalJava are equally unlikely to waste their small screen space and low resolution on a 1970s-era interface.

Consoles in Applets

As well as being unpredictable across platforms, consoles are also unpredictable across web browsers. Netscape provides a “Java console,” shown in Figure 1.4, that’s used for applets that want to write on System.out. By typing a question mark, you get a list of useful debugging commands that can be executed from the console.

Netscape Navigator’s Java console window

Figure 1-4. Netscape Navigator’s Java console window

The console is turned off by default, and users must explicitly request that it be turned on. Therefore, it’s a bad idea to use it in production applets, though it’s often useful for debugging. Furthermore, mixing and matching a command line and a graphical user interface is generally a bad idea.

Some versions of Microsoft Internet Explorer do not have a visible console. Instead, data written on System.out appears in a log file. On Windows, this file can be found at %Windir%\ java\ javalog.txt. (This probably expands to something like C:\Windows\java\ javalog.txt , depending on the exact value of the %Windir% environment variable). On the Mac the log file is called Java Message Log.html and resides in the same folder as Internet Explorer. To turn this option on, select the Options... menu item from the View menu, click the Advanced tab, then check Enable Java Logging.

If you absolutely must use a console in your applet, the following list shows several third-party consoles that work in Internet Explorer. Some provide additional features over the bare-bones implementation of Netscape. Of course, URLs can get stale rather quickly. If for some reason none of these work for you, you can always do what I did to collect them in the first place: go to http://developer.java.sun.com/developer and search for “console.”

Arial Bardin’s Java Console

http://www.cadviewer.com/JavaConsole.html

Jamie Cansdale’s Java Console and Class Flusher

http://www.obsolete.com/people/cansdale/java/java_console/index.htm

Frederic Lavigne’s Package fr.l2f

http://www.l2fprod.com

System.out

System.out is the first instance of the OutputStream class most programmers encounter. In fact, it’s often encountered before programmers know what a class or an output stream is. Specifically, System.out is the static out field of the java.lang.System class. It’s an instance of java.io.PrintStream, a subclass of java.io.OutputStream.

System.out corresponds to stdout in Unix or C. Normally, output sent to System.out appears on the console. As a general rule, the console converts the numeric byte data System.out sends to it into ASCII or ISO Latin-1 text. Thus, the following lines write the string “Hello World!” on the console:

byte[] hello = {72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100, 33, 10, 
                13};
System.out.write(hello);

System.err

Unix and C programmers are familiar with stderr, which is commonly used for error messages. stderr is a separate file pointer from stdout, but often means the same thing. Generally, stderr and stdout both send data to the console, whatever that is. However, stdout and stderr can be redirected to different places. For instance, output can be redirected to a file while error messages still appear on the console.

System.err is Java’s version of stderr. Like System.out, System.err is an instance of java.io.PrintStream , a subclass of java.io.OutputStream . System.err is most commonly used inside the catch clause of a try/catch block like this:

try {
  // Do something that may throw an exception.
}
catch (Exception e) {
  System.err.println(e);
}

Finished programs shouldn’t have much need for System.err, but it is useful while you’re debugging.

System.in

System.in is the input stream connected to the console, much as System.out is the output stream connected to the console. In Unix or C terms, System.in is stdin and can be redirected from a shell in the same fashion. System.in is the static in field of the java.lang.System class. It’s an instance of java.io.InputStream, at least as far as is documented.

Past what’s documented, System.in is really a java.io.BufferedInputStream. BufferedInputStream doesn’t declare any new methods, just overrides the ones already declared in java.io.InputStream. Buffered input streams read data in large chunks into a buffer, then parcel it out in requested sizes. This can be more efficient than reading one character at a time. Otherwise, it’s completely transparent to the programmer.

The main significance of this is that each byte is not presented to be read as the user types it on System.in. Instead, input enters the program one line at a time. This allows a user typing into the console to backspace over and correct mistakes. Java does not allow you to put the console into “raw mode,” where each character becomes available as soon as it’s typed, including characters like backspace and delete.

In an application run from the command line, System.in is taken from the window where the program was started; that is, the console. In applets, the same console window that’s used for System.out is also used for System.in ; however, Internet Explorer has no way to read from System.in in an applet. In Netscape, the console is turned off by default, and users must explicitly request that it be turned on.

The user types into the console using the platform’s default character set, typically ASCII or some superset thereof. The data is converted into numeric bytes when read. For example, if the user types “Hello World!” and hits the return or enter key, the following bytes will be read from System.in in this order:

72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100, 33, 10, 13

Many programs that run from the command line and read input from System.in require you to enter the “end of stream” character, also known as the “end of file” or EOF character, to terminate a program normally. How this is entered is platform-dependent. On Unix and the Mac, Ctrl-D generally indicates end of stream. On Windows, Ctrl-Z does. In some cases it may be necessary to type this character alone on a line. That is, you may need to hit Return/Ctrl-Z or Return/Ctrl-D before Java will recognize the end of stream.

Redirecting System.out, System.in, and System.err

In a shell you often redirect stdout, stdin, or stderr. For example, to specify that output from the Java program OptimumBattingOrder goes into the file yankees99.out and that input for that program is read from the file yankees99.tab, you might type:

% java OptimumBattingOrder < yankees99.tab > yankees99.out

Redirection in a DOS shell is the same. It’s a little more complicated in graphical environments, but not particularly difficult. To give one example, the JBindery tool included in Apple’s Macintosh Runtime for Java, shown in Figure 1.5, provides a simple pop-up menu interface for selecting a file, /dev/null, or a message window as the target of System.out or source for System.in.

Redirecting stdout and stdin from JBindery

Figure 1-5. Redirecting stdout and stdin from JBindery

It’s sometimes convenient to be able to redirect System.out, System.in, and System.err from inside the running program. The following three static methods in the java.lang.System class do exactly that:

public static void setIn(InputStream in)
public static void setOut(PrintStream out)
public static void setErr(PrintStream err)

For example, to specify that data written on System.out is sent to the file yankees99.out and data read from System.in comes from yankees99.tab, you could write:

System.setIn(new FileInputStream("yankees99.tab"));
System.setOut(new PrintStream(new FileOutputStream("yankees99.out")));

These methods are especially useful when making a quick and dirty port of a program that makes heavy use of System.out, System.in, or System.err from an application to an applet. However, there is no absolute guarantee that console redirection will be allowed in all web browsers. Internet Explorer 4.0b2 allowed it, but the released version does not. HotJava 1.1 allows it with the security settings turned down, but not with security at the default level. Netscape Navigator 4.0 and 4.5 and HotJava 1.0 do not allow console redirection.

The SecurityManager class does not have a specific method to test whether or not redirecting System.out or System.err is allowed. However, in Java 1.1 Sun’s JDK checks whether this is permitted by calling checkExec("setIO"). (The source code contains a comment to the effect that there should be a separate method for this sort of check in future versions of Java.) checkExec() determines whether the security manager allows a subprocess called setio to be spawned. The AppletSecurity security manager used by appletviewer in JDK 1.1 always disallows this call.

In Java 2 the security architecture has changed, but the effect is the same. A RuntimePermission object with the name setIO and no actions is passed to AccessController.checkPermission(). This method throws an AccessControlException, a subclass of SecurityException, if redirection is not allowed.



[4] Console input is supported in MRJ 2.1ea2 and presumably later releases.

Get Java I/O now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.