Input is any information that is needed by your program to complete its execution. There are many forms that program input may take. javabook2
programs use graphical components like an InputBox to accept and return the character string that is typed by the user. You are certainly familiar with
programs that are controlled simply by clicking the mouse in a specific area of the screen. Still other programs, like word processing programs, get
some of their input from a file that is stored on the computer's floppy or hard disk drive. Some programs, like web browsers, get their data from a network connection,
while others get data from devices like scanners, digital cameras and microphones. The possibilities are limited only by computer scientists' imagination.
Output is any information that the program must convey to the user. The information you see on your computer screen is being output by one or more programs that are currently running on your computer. When you decide to print a document, a program is told to send some output to the printer. Any sound that your computer makes is because some program sent output to the speakers on your computer. The possibilities for program output are also limited only by our imaginations.
Throughout the semester, we have been performing input and output through the use of several of the classes in the javabook2
package provided by the textbook's author. We used javabook2
classes instead of the standard Java Language classes because they are easier for beginning programmers to
understand and use.
One of the reasons the javabook2
classes are easier to use than the standard java classes is because they automatically handle several potential error conditions that may occur when a program needs to get input from the user. If a user enters letters when a program is expecting numbers, an
exception [error]
will occur if the program assumes incorrectly that it has a valid integer to use in calculations. Programs must be written to survive bad input by the user. One way to do this is to ensure that only valid input is accepted. javabook2
classes like InputBox
ensure that only valid integers
are accepted when the programmer calls the getInteger
method.
Another reason that we use javabook2
classes instead of the standard library is for simplicity. Each javabook2
class has a simple constructor or constructors and several intuitive methods for accomplishing common input and output tasks. For example, to prompt and accept an integer input by the user is very
straightforward using classes from the javabook2
package. You declare and create an InputBox
and call the getInteger
method. However, the same action becomes much more complex using only standard java classes. You may wonder why the standard Java
classes are not as easy as the javabook2
classes and the answer is flexibility. Standard Java classes are designed to be very flexible to support the wide variety of input and output options available now and in the future. This flexibility comes at the cost of increased complexity.
The console window is the [black] window that is automatically launched when you run a program from within CodeWarrior. Console input is any input that is entered in the console window instead of typing it into a field or dialog box that pops up in a window. Until now, we have been using an instance of
the InputBox
class and one of its get
methods. For example, when the getString
method was called, a dialog window popped up, and the user was expected to enter information into the blank field. Whatever the user typed was returned to the program in the
form of a String
object.
There are other ways to get information. In many cases, the user must be told that they should enter some information. This is known as prompting the user. A user prompt is a line of text that is output to the user that explains what information they should input next. We can prompt the user by displaying information in a dialog box, a program frame or even the console window. All programs that require the user to input information while the program is running, must prompt the user for that information in some manner.
When a program is waiting for input at the console, there is a blinking cursor in the console window indicating that the user should type some information. The user will only know what information to type, if the program describes that information in the form of a user prompt. (See Console Output for more information on user prompts.)
The use of several of the Java I/O classes are required to successfully receive input that is typed by the user. The java.io
package contains most, if not all, of the classes you will need to use. Don't worry, you won't need to use all 50+ classes. But, you will need to learn about and
use at least three of them. All three classes are in the java.io
package. Either use the fully qualified name shown or import the java.io
package.
java.io.InputStream
- stores information about the connection between an input device and the computer or program.java.io.InputStreamReader
- used to translate data bytes received from InputStream
objects into a stream of characters.java.io.BufferedReader
- used to buffer (store) the input received from a InputStreamReader
object. This is done to improve the efficiency. Input devices are much slower than the computer's
processor and buffering the data reduces the number of times the CPU has to interact with the device itself.None of these classes has a method as convenient and as error proof as the getString
method you've used. However, the BufferedReader
class does have a method called readLine
that is almost as good, and does return a line of text as typed by
the user. There are two available constructors for creating a BufferedReader
object. For console input, we will use the one that requires only one argument, an instance of a Reader
object. That means we need to create an instance of the class java.io.Reader
.
The InputStreamReader
class extends the Reader
class. Here's an analogy to explain extends: All Robins are Birds, but not all Birds are Robins. Therefore, Robin extends Bird. If someone needs a Bird, then a Robin can be used. This means that any
instance of the InputStreamReader
class can be used whenever an instance of the Reader
class is required. The inheritance hierarchy of the InputStreamReader class shows that it extends the Reader
class because the Reader
class is higher in the hierarchy tree.
We will create an instance of the InputStreamReader
class to be used to create the BufferedReader
that we want. We choose to create an InputStreamReader
instead of a Reader
object because we want to get input from an InputStream
. Later, you
will see that File I/O will require the use of a different type of Reader
object.
What do we need to have in order to create an instance of the InputStreamReader
class? According to the Java API, we will need an InputStream
object. Oh, now I see why we needed all three classes! Luckily, part of our work is done for us. The System
class in the java.lang
package automatically creates an InputStream
object that is connected to the keyboard. It is called System.in
and is part of the java.lang
package.
We will use the System.in
object to create an instance of the InputStreamReader
class and then use that object to create an instance of the BufferedReader
class. That's not so bad, but still not as easy as creating an InputBox
, wouldn't you agree?
System.in
object to create an InputStreamReader
object.InputStreamReader
object to create a BufferedReader
object.BufferedReader
object to read a line of text from the user.// 1. Create an InputStreamReader using the standard input stream InputStreamReader isr = new InputStreamReader( System.in ); // 2. Create a BufferedReader using the InputStreamReader created. BufferedReader stdin = new BufferedReader( isr ); // 3. Don't forget to prompt the user System.out.print( "Type some data for the program: " ); // 4. Use the BufferedReader to read a line of text from the user. String input = stdin.readLine(); // 5. Now, you can do anything with the input string that you need to. // Like, output it to the user. System.out.println( "input = " + input );
Yes, most Java programmers combine steps 1 & 2 and create only one instance of the BufferedReader
for use throughout their entire program. All keyboard operations will use that single shared BufferedReader
object. The code below is placed with other class data members and is
not inside any method.
// 1&2. Create a single shared BufferedReader for keyboard input. private static BufferedReader stdin = new BufferedReader( new InputStreamReader( System.in ) );
Did you remember to import the java.io
classes? The BufferedReader
(and other I/O classes) are not in the standard java.lang
package. You must import the java.io
package to declare and create instances of any of the Java I/O classes. Add the
import java.io.*;
statement to your list of other import statements.
You will also have to inform the compiler that you are calling a method that may cause a checked exception
to occur. Add the phrase throws IOException
to the header of any method that calls stdin.readLine()
. You
will also need to add this clause to any method that calls your method that calls readLine
. Here's a complete program example that prompts the user for input and then repeats that data to the console window:
import java.io.*; // needed for BufferedReader, InputStreamReader, etc. /** A Java program that demonstrates console based input and output. */ public class MyConsoleIO { // Create a single shared BufferedReader for keyboard input private static BufferedReader stdin = new BufferedReader( new InputStreamReader( System.in ) ); // Program execution starts here public static void main ( String [] args ) throws IOException { // Prompt the user System.out.print( "Type some data for the program: " ); // Read a line of text from the user. String input = stdin.readLine(); // Display the input back to the user. System.out.println( "input = " + input ); } // end main method } // end MyConsoleIO class
Getting data from the user isn't so hard after all. But, it does require some additional work. There is even more work to do, if you want to get an integer (or other numeric value) from the user. If the user types in "123", that will be still be returned as a String
object by
the readLine
method of BufferedReader
. You will need to
parse [convert] the String
into an int
value if you wish to store it in an int
variable or data member. Here's how:
String
of characters that is in an integer format, eg. "123".String input = stdin.readLine(); // from console input example above.
Integer
class to parse the string of characters into an integer. int number = Integer.parseInt( input ); // converts a String into an int value
The Integer class contains conversion methods for changing String data into int values and vice versa. The Integer class is one of several
wrapper classes that are defined in the standard Java API. Wrapper classes have class methods for parsing and are also used when you need to store a
primitive value as an object. More on this use later in the course.String
into an int
value. The parseInt
method of the Integer
class performs this action. Be sure to review the Integer
class javadoc for more information about this and other methods of the Integer class.The parseInt
method declares that it may throw a NumberFormatException
. If the user types any string of characters that can't be parsed into an int
value, a NumberFormatException
will be thrown and the program will crash. That can't be a
good thing! But, there is something that you as the programmer can do to keep your program from crashing. You can catch the NumberFormatException
. If you don't know what an exception is, read about them in Java Exceptions. There is an example on catching a NumberFormatException.
We have used System.out.print(...)
and System.out.println(...)
statements as an alternative to creating and displaying an OutputBox
or MessageBox
for displaying simple text messages to the user. This is an important output alternative, since javabook2
classes and other graphic user interface (GUI) objects are not readily available in some programming environments. You may of course write your own GUI classes if they're not available, but that is beyond the scope of this course. It is much more likely that you will simply use the available output options
of the programming environment that you are working in.
Most programming languages have the ability to display a string of characters to the screen or some other standard display device. We call this console output because the string of characters appears in a console window. The System.out
object is an instance of the PrintStream
class, which is a type of Stream
.
A Stream
object is used to store information needed to connect a computer program to an input or output device. Just like there is a Reader
object that adds functionality to input streams, there is a Printer
object that adds functionality to output streams. The PrintStream
class extends the Printer
class and contains definitions for all of the versions of the print
and println
methods that we use to display information like user prompts or results of calculations, etc.
Console output in Java is very easy because the print
and println
methods will work with any type of data. There is a separate version of each of these methods in the PrintStream
class so that this is possible. There is also a
version of the print
and println
methods that will print information for any object. But, how did we get a PrintStream
object in the first place?
The java.lang.System
class creates three different I/O streams automatically for us when our application begins execution. Each of these streams is public and static so that we can access them directly without having to create an instance of the System
class. We have already
used the InputStream
object named System.in
in the discussion on console input. The other two stream objects are named System.out
and System.err.
Each of these objects is an instance of the PrintStream
class and is
available for use in displaying information to the computer screen.
For example, if the following variables are defined,
int x = 3; double rate = 5.5; boolean playing = true; String phrase = "The winner is ";
they can all be printed using print
or println
as follows:
System.out.print( "x = " + x + " rate = " ); System.out.println( rate ); System.out.println( "playing = " + playing ); System.out.println( phrase + "Deb" );
We can also print other types of data, including other objects, using the print
and println
methods. The following code fragment shows the command syntax for printing a Wanderer object.
Wanderer wanderer1 = new Wanderer( "Wilma", Color.orange );
System.out.println( wanderer1 );
In this case, the program prints out some cryptic information about the Wanderer. It is the class name, an @
symbol and the hexidecimal representation of the hashcode. The output looks like the following for the first Wanderer object I created.
Wanderer@13fac
Each object created has its own hashcode that can be used to distinguish it from other objects. However, hashcodes are not very readable for most users, so there is a way for the programmer to redefine what information is printed. The information that is displayed when an object is printed using the print
method is defined by an instance method named toString
. Every class has a version of the toString
method already defined that returns the information as described above. All classes inherit this method from the java.lang.Object
class.
To redefine the toString
method, you override the default version by defining a method with the same visibility and method signature as the inherited version of the method. The toString
method of my Wanderer
class can be
overridden as follows:
/** * Returns a string representing this * instance of the Wanderer class. */ public String toString() { String coords = "(" + myLoc.getX() + "," + myLoc.getY() + ")"; return myName + " is at " + coords; }
Now, when the print
or println
method is used to print a Wanderer
object, the new version of the toString
method will be called instead of the version defined in the Object
class. The String
that is printed by the println
method will look something like this:
Wilma is at (11,3)
Each class can and should override the toString
method to return a String
of characters that is more descriptive of the object than the default version provided by the Object
class. This method can be called by any method that needs a String
that describes the object.
The print
or println
methods of the PrintStream
class should be adequate to produce most screen output. The only other type of output we will cover in this course is file output. Other output devices require more
specialized output objects and won't be covered in this course.
As mentioned above, data can be read from a variety of different sources, including data files stored on devices such as hard disk drives and floppy drives. The file will need to be opened and a BufferedReader
will be attached to the file object. The process is actually very
similar to the console input example above. The difference is that the BufferedReader
will be created from a FileReader
object instead of an InputStreamReader
object. Your textbook describes file input when the file stores individual bytes. This section focuses
on inputting characters rather than data bytes.
The discussion and examples in this document explain the procedure when the file to be read is a text file that has valid ASCII characters to represent the data. Here are two new Java I/O classes to review:
java.io.File
- stores information about a file on a computer drive.java.io.FileReader
- used to translate data bytes from File
objects into a stream of characters.Here's a code fragment to illustrate reading a text file. The readLine
method may cause an IOException
which is a checked exception, so be sure to catch the exception or add the throws IOException
to the method header. See the Java Exceptions web page for more information on handling checked exceptions.
System.out.print( "Enter the filename: " ); // Prompt the user for a file name String fileName = stdin.readLine(); // get a file name from the user java.io.File file = java.io.new File( fileName ); // create a File object if ( file.exists() ) // check that the file exists { // before trying to create a // BufferedReader // Create a BufferedReader from the file java.io.BufferedReader inFile = new java.io.BufferedReader( new java.io.FileReader( file ) ); // For each line in the file, read in the line and display it with the line number int lineNum = 0; // Compare the results of calling the readLine method to null // to determine if you are at the end of the file. String line = inFile.readLine(); while ( line != null ) { System.out.println( ++lineNum + ": " + line ); line = inFile.readLine(); } // Close the buffered reader input stream attached to the file inFile.close(); }
import java.io.*
classes.readLine
method of a BufferedReader
object. See the Checked Exceptions section of the Java Exceptions page for more
information.readLine
will return valid data. You should test the return value of calling the readLine
method against null
before trying to use that data. Here's an example:
int lineNum = 0; String lineData = inFile.readLine(); while ( lineData != null ) { // Do something with the line of data System.out.println( ++lineNum + ": " + lineData ); lineData = inFile.readLine(); }
BufferedReader
object when you're done reading data from the file.throws IOException
clause.When you are reading data into your program from a text file, you may need to interpret certain parts of each line differently. This is especially true if you need your program to create objects from text data contained in a file. Individual data items can be placed on different lines of the input data
file, but this creates very long files. It is much more common to place all of the data items for one object on the same line and separate each item with some special character, called a delimiter. In this type of data file, each line of the file represents one record or one object. The example
data file "student_scores.txt
" shown below, contains data for three students and three exams scores for each student.
Each line of input is interpreted as a string of characters for the name, that is followed by three integers for each object created. The delimiter character is the ':'
in the above data file.
The process of splitting a line of text into different parts is known as tokenizing, and each piece is a token. The standard Java library includes a class called, StringTokenizer
that makes this process much more convenient for Java programmers. Without this class, you would
need to use nested repetition and selection statements to process each character one at a time and determine if it is part of the name or one of the exam scores and then store it accordingly. Java programmers simply need to learn how to construct a StringTokenizer
object and what methods are
available. Refer to the StringTokenizer javadoc for more detailed information on methods other than those presented here.
A StringTokenizer
object is created from a String
object. You can access each token similar to the way in which you accessed each
Wanderer
using the BallTeam
object in Assignment #1. Use the hasMoreTokens
method
to determine if there are any remaining tokens to process. Use the nextToken
method to return the next token as a String
object. There is also a countTokens
method that returns the number of remaining tokens available for a particular
instance of the StringTokenizer
class.
The StringTokenizer
class is in the java.util
package, so you must fully qualify the name as java.util.StringTokenizer
or import the class. Here is a code fragment that reads the file shown above and computes the average score for each student listed. If you call nextToken
when there are no tokens remaining, a java.util.NoSuchElementException
will occur.
// Make sure that the file student_scores.txt exists and has // valid data records. Otherwise, exceptions will occur. File gradeFile = new File( "student_scores.txt" ); if ( gradeFile.exists() ) { // Create the buffered reader for reading the file BufferedReader inFile = new BufferedReader( new FileReader( gradeFile ) ); // Get the first line of the file String line = inFile.readLine(); // If line is not end of file continue while ( line != null ) { // Create a StringTokenizer with a colon sign as a delimiter java.util.StringTokenizer st = new java.util.StringTokenizer( line, ":" ); // Display the content of the first token System.out.print( " Name: " + st.nextToken() ); // Display the total number of tokens remaining this string int numScores = st.countTokens(); // Initialize the sum to zero int sum = 0; // Get each score, add it to the sum and print it for ( int i=1; i <= numScores; i++ ) { int score = Integer.parseInt( st.nextToken() ); sum += score; } // Display the average score for this student System.out.println( " average = " + sum/numScores ); // Read next line of the file line = inFile.readLine(); } // end while not at end of file // Close the BufferedReader inFile.close(); } // end if the grade file doesn't exist
Writing data to a file is similar to writing data to the screen. You will open a file for writing and then print to that file any data that you would like to store there. You must remember to close the file or risk having some data not be written and saved to the file. We will use each of these classes.
java.io.FileWriter
- used to open a file and connect an output stream to it.java.io.PrintWriter
- used to write strings of characters (instead of bytes) to any Writer object.When you intend to write data to a file, you should consider what the appropriate action to take is, if the file already exists. The safest option is to ask the user what to do, and then allow the user to choose overwrite the file, choose a different filename or cancel the operation. The
example shown below assumes that the file opened by the FileWriter
object will be overwritten if it already exists. If you do not want to overwrite the file if it already exists, then you must create and test a File
object first. The exists
method of the
File
class will return true
if the file already exists.
// Create a FileWriter attached to a file named "out.txt". // The second parameter sets whether or not new data // will be appended to the end of the file or the beginning. // false means that this file will be overwritten. java.io.FileWriter fw = new java.io.FileWriter( "out.txt", false ); // Create a PrintWriter that automatically flushes data // to the output file whenever the println method is used. java.io.PrintWriter pw = new java.io.PrintWriter( fw, true ); // Buffer some data to write to the file (doesn't actually write until flush) pw.print( "Some test data that will be written when flush is called."); // Flush all buffered data to the file. pw.flush(); // Write some data and automatically flush it to the file. pw.println( data ); // Close the PrintWriter for added safety. pw.close();
The nice thing about using a PrintWriter
object is that you are already familiar with the print
and println
methods that are defined for all PrintWriter
objects. By choosing the constructor that accepts a String
for
the filename and a boolean
value, we are able to set the PrintWriter
object so that it will always flush the data buffer on all calls to println
. This is safer, but less efficient. It is more efficient to wait until the buffer is full before writing to
disk. In that case, the flush
method must be called or the file must be closed to flush the remaining data from the buffer.
Input and output using the standard Java library of classes is somewhat more complex than using javabook2
classes. By using and experimenting with each of the techniques presented here, you will be able to perform some of the most common input and output operations in your Java programs.
ConsoleIO.java has additional examples of console based input and output, written by Jim Skrentny.
FileIO.java has an additional examples of file based input and output, written by Jim Skrentny.
Copyright © 2002 Deb Deppeler. Last update on 11/21/2002 08:26 AM