Algorithms and OOD (CSC 207 2014F) : Readings

Basic Textual Input and Output in Java


Summary: We introduce (or re-introduce) the basics of input and output in Java, including input from the keyboard and files, and output to the screen and to files.

Important Classes
Prerequisites: Basics of Java.

Input and Output

In the early days of computing, programs were run only in batch mode. That is, you would start the program, wait for it to compute results (or crash), and then read the results (or error log). Initially, programmers coded any values the program would use directly into the program. Soon thereafter, however, they realized that it was far more general to place the input to a program (and the output from a program) in separate files.

With the advent of interactive computing systems, it became even more important for programs to be able to read input from a variety of sources and to send output to a variety of targets. In early interactive systems, most input was based on text that came from the keyboard and that went to a monitor or printer that showed only alphanumeric characters. Hence, the focus of early input and output commands was textual input and output.

Even with the creation of modern window-based systems, in which input can come from mice, touchscreens, and a variety of other devices and output can be graphical and auditory as well as textual, it is still useful to be able to read and write text, if only to save comments to a log and to gather data from a file.

While there are a variety of graphical input and output mechanisms, it is still useful to be able to do basic textual input and output. input and output. In this reading (and the corresponding lab), we will explore the basics of textual input and output.

Output Basics

You should already know most of what you need to know about simple output in Java. The primary kind of object for output (at least the most basic output) is a java.io.PrintWriter. You can create PrintWriters that print to the screen and PrintWriters that print to a file.

To create a PrintWriter for the sceen, use something the following.

java.io.PrintWriter pen;
pen = new java.io.PrintWriter (System.out, true);

Two shorthands can simplify this code. First, if you import java.io.PrintWriter, you need only provide the basic class name. Second, you can put assignment on the same line as declaration. The result is therefore

PrintWriter pen = new PrintWriter (System.out, true);

Preparing a PrintWriter for a file is nearly as simple. First, you must create an object in class java.io.File. Second, you build a new PrintWriter with that file as a parameters. In verbose form,

java.io.File outfile;
java.io.PrintWriter pen;
outfile = new java.io.File ("name-of-file");
pen = new java.io.PrintWriter (outfile);

Custom suggests that you close a file when you're done with it.

pen.close ();

One benefit of creating the same kind of object for either kind of output is that it's very easy to update your program to write to a file instead of to the screen (or vice versa). You can also use a PrintWriter to print to a network connection.

You may find that the PrintWriter output methods don't quite behave the way you expect. That is, you may print something but it won't immediately appear on the screen. (This behavior is particularly painful when you are prompting the user.) Many programmers find the delayed printing of print somewhat confusing. After all, you've told the PrintWriter to print, so why doesn't it do so immediately? It turns out that for some applications, it is much more efficient to delay printing until a certain amount of text has been printed. The designers of Java, like many designers before them, decided to make “wait until there's enough to write” the default behavior and provided a special procedure named flush for those who want different behavior. When creating a new PrintWriter, you can set it to “autoflush”, which means that it flushes the output buffer whenever you print a newline.

PrintWriter objects provide a few basic methods:

  • print (what-to-print): Queue for printing the given value to the appropriate destination. Does not print a carriage return, so subsequent output will appear on the same line.
  • println (what-to-print): Print the given value to the appropriate destination followed by a carriage return. The println procedure “flushes” the output only if you've created the PrintWriter with the autoflush flag set to true.
  • println (): Print a carriage return.
  • flush (): Finishes printing anything queued by print (and by println if autoflush is not set.
  • format(format-string, value, ..., value): Print values using a printf-style format string.
  • close (): Closes a PrintWriter that we're done using. By closing a PrintWriter, you also guarantee that you flush the output.

Input Basics

Most simple input in Java is done using objects from class java.io.BufferedReader. As you might expect, you can create buffered readers that read from the keyboard and buffered readers that read from files. However, before creating a BufferedReader, you must create an intermediate object, either an java.io.InputStreamReader or a java.io.FileReader.

For example, to create an object to read from the keyboard, you would use code like the following

java.io.BufferedReader eyes;
java.io.InputStreamReader istream;
istream = new java.io.InputStreamReader (System.in);
eyes = new java.io.BufferedReader (istream);

Similarly, to create an object to read from a file, you would use code like the following

java.io.File infile;
java.io.FileReader istream;
infile = new java.io.File (name-of-file);
istream = new java.io.FileReader (infile);
eyes = new BufferedReader (istream);

Note that the names you choose for your objects need not match the ones that I've chosen.

BufferedReader objects provide a variety of basic methods. You can use read to read a single character and readLine to read the next line of input and returns it as a string. The line read does not include the carriage return or line feed that typically ends lines. You typically assign the line read to a variable, as in

 
// Declarations
...
String name; 
...
// Commands
...
name = eyes.readLine (); 

You may, of course, also use the line read as you may use any string, such as to print it out directly.

pen.println (eyes.readLine ());

When you're done with input, you should close it, just as you close output.

eyes.close ();

Rewinding Input

One nice part about BufferedReader objects is that they permit you to “back up” in the input file. As you will note from the documentation, you can use mark to indicate a place to which you will rewind and reset to rewind to that place. Note that mark takes one parameter, readAheadLimit, a number that indicates the maximum number of characters that will be read before the next call to reset. For example, here is some silly code that reads two lines from a file and then prepares to read the first of the two lines again.

eyes.mark (1024);
pen.println (eyes.readLine ());
pen.println (eyes.readLine ());
eyes.reset ();

Why would you want to rewind input? Typically, because you want to look ahead for some value to determine how best to parse the input. But there are a host of other reasons.