Reading Standard Input

Problem

Despite Rusty’s comments, you really do need to read from the standard input, or console. One reason is that simple test programs are often console-driven. Another is that some programs naturally require a lot of interaction with the user and you want something faster than a GUI (consider an interactive mathematics or statistical exploration program).

Solution

To read bytes, wrap a BufferedInputStream( ) around System.in. For the more common case of reading text, use an InputStreamReader and a BufferedReader .

Discussion

On most non-Macintosh desktop platforms, there is a notion of standard input -- a keyboard, a file, or the output from another program -- and standard output -- a terminal window, a printer, a file on disk, or the input to yet another program. Most such systems also support a standard error output, so that error messages can be seen by the user even if the standard output is being redirected. When programs on these platforms start up, the three streams are preassigned to particular platform-dependent handles, or file descriptors. The net result is that ordinary programs on these operating systems can read the standard input or write to the standard output or standard error stream without having to open any files or make any other special arrangements.

Java continues this tradition, and enshrines it in the Java Standard Edition’s System class. The static variables System.in , System.out, and System.err are connected to the three operating system streams before your program begins execution (an application is free to reassign these; see Section 9.7). So to read the standard input, you need only refer to the variable System.in and call its methods. For example, to read one byte from the standard input, you call the read method of System.in, which returns the byte in an int variable:

int b = System.in.read(  );

But is that enough? No, because the read( ) method can throw an IOException. So you must either declare that your program throws an IOException, as in:

public static void main(String ap[]) throws IOException {

Or, you can put a try/catch block around the read method:

int b = 0;
try {
    b = System.in.read(  );
} catch (Exception e) {
    System.out.println("Caught " + e);
}
System.out.println("Read this data: " + (char)b);

Note that I cavalierly convert the byte to a char for printing, assuming that you’ve typed a valid character in the terminal window.

Well, that certainly works, and gives you the ability to read a byte at a time from the standard input. But most applications are designed in terms of larger units, such as a line of text. For reading characters of text, using an input character converter so that your program will work with multiple input encodings around the world, you’ll want to use a Reader class. The particular subclass that allows you to read lines of characters is a BufferedReader . But there’s a hitch. Remember that I said there are two categories of input classes, Streams and Readers? But I also said that System.in is a Stream, and you want a Reader. How to get from a Stream to a Reader? There is a “crossover” class called an InputStream reader that is tailor-made for this purpose. Just pass your Stream (like System.in) to the InputStreamReader constructor, and you get back a Reader, which you in turn pass to the BufferedReader constructor. The usual idiom for writing this in Java is to nest the constructor calls:

BufferedReader is = new BufferedReader(new InputStreamReader(System.in);

Then you can read lines of text from the standard input using the readLine( ) method. This method takes no argument, and returns a String that is made up for you by readLine( ) containing the characters (converted to Unicode) from the next line of text in the file. If there are no more lines of text, then the constant null is returned.

import java.io.*;

/**
 * Read and print, using BufferedReader from System.in, onto System.out
 */
public class CatStdin {

    public static void main(String av[]) {
        try {
            BufferedReader is = new BufferedReader(
                new InputStreamReader(System.in));
            String inputLine;

            while ((inputLine = is.readLine(  )) != null) {
                System.out.println(inputLine);
            }
            is.close(  );
        } catch (IOException e) {
            System.out.println("IOException: " + e);
        }
    }
}

And because it’s something that people ask me over and over, I’ll show how to read an Integer from the standard input:

import java.io.*;
/**
 * Read an int from Standard Input
 */
public class ReadStdinInt {
    public static void main(String[] ap) {
        String line = null;
        int val = 0;
        try {
            BufferedReader is = new BufferedReader(
                new InputStreamReader(System.in));
            line = is.readLine(  );
            val = Integer.parseInt(line);
        } catch (NumberFormatException ex) {
            System.err.println("Not a valid number: " + line);
        } catch (IOException e) {
            System.err.println("Unexpected IO ERROR: " + e);
        }
        System.out.println("I read this number: " + val);
    }
}

There are many other things you might want to do with lines of text read from a Reader. In the demo program shown in this recipe, I just printed them. In the demo program in Section 9.4, I convert them to integer values using Integer.parseInt( ) (also see Section 5.2) or using a DecimalFormat (Section 5.8). You can interpret them as dates (Section 6.6), or break them into words with a StringTokenizer (Section 3.3). You can also process the lines as you read them; several methods for doing so are listed in Section 9.13.

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

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