Section 2.4
Text Input and Output
FOR SOME UNFATHOMABLE REASON, Java seems
to lack any reasonable built-in subroutines for reading
data typed in by the user. You've already seen that output can be
displayed to the user using the subroutine System.out.print.
This subroutine is part of a pre-defined object called
System.out. The purpose of this object is precisely
to display output to the user. There is a corresponding
object called System.in that exists to read data
input by the user, but it provides only very primitive input
facilities, and it requires some advanced Java programming
skills to use it effectively.
There is some excuse for this, since Java
is meant mainly to write programs for Graphical User Interfaces,
and those programs have their own style of input/output, which
is implemented in Java. However, basic support is needed
for input/output in old-fashioned non-GUI programs. Fortunately,
it is possible to extend Java by creating new classes that
provide subroutines that are not available in the classes which are
a standard part of the language. As soon as a new class is available,
the subroutines that it contains can be used in exactly the same way
as built-in routines.
For example, I've written a class called TextIO
that defines subroutines for reading values typed
by the user. The subroutines in this class make it possible to
get input from the standard input object, System.in,
without knowing about the advanced aspects of Java that
are needed to use System.in directly.
TextIO also contains a set of output subroutines. The
output subroutines are similar to those provided in System.out,
but they provide a few additional features. You can use whichever
set of output subroutines you prefer, and you can even mix them
in the same program.
To use the TextIO class, you must make sure that the
class is available to your program. What this means depends on
the Java programming environment that you are using.
See Appendix 2
for information about programming environments. In general,
you just have to add the compiled file, TextIO.class,
to the directory that contains your main program. You can obtain
the compiled class file by compiling the source code,
TextIO.java.
The input routines in the TextIO class are static member
functions. (Static member functions were introduced in the previous section.)
Let's suppose that you want your program to read an integer typed in by the user.
The TextIO class contains a static member function named getInt
that you can use for this purpose. Since this function is contained in the TextIO
class, you have to refer to it in your program as TextIO.getInt. The function
has no parameters, so a call to the function takes the form "TextIO.getInt()".
This function call represents the int value typed by the user, and you have to
do something with the returned value, such as assign it to a variable. For example,
if userInput is a variable of type int (created with a declaration
statement "int userInput;"), then you could use the
assignment statement
userInput = TextIO.getInt();
When the computer executes this statement, it will wait for the
user to type in an integer value. The value typed will be returned by the
function, and it will be stored in the variable, userInput.
Here is a complete program that uses TextIO.getInt
to read a number typed by the user and then prints out the
square of the number that the user types:
public class PrintSquare {
public static void main(String[] args) {
// A program that computes and prints the square
// of a number input by the user.
int userInput; // the number input by the user
int square; // the userInput, multiplied by itself
System.out.print("Please type a number: ");
userInput = TextIO.getInt();
square = userInput * userInput;
System.out.print("The square of that number is ");
System.out.println(square);
} // end of main()
} //end of class PrintSquare
Here's an applet that simulates this program. When you run the program, it
will display the message "Please type a number: " and will pause
until you type a response. (If the applet does not
respond to your typing, you might have to click on it to activate it.
In some browsers, you might also need to leave the mouse cursor inside
the applet for it to recognize your typing.)
The TextIO class contains static member subroutines TextIO.put
and TextIO.putln that can be used in the same way as System.out.print
and System.out.println. For example, although there is no particular advantage in
doing so in this case, you could replace the two lines
System.out.print("The square of that number is ");
System.out.println(square);
with
TextIO.put("The square of that number is ");
TextIO.putln(square);
For the next few chapters,
I will use TextIO for input in all my examples, and
I will often use it for output.
Keep in mind that TextIO can only be used in a program
if TextIO.class is available to that program. It is not
built into Java, as the System class is.
Let's look a little more closely at the built-in output
subroutines System.out.print and System.out.println.
Each of these subroutines can be used with one parameter, where
the parameter can be any value of type byte, short,
int, long, float, double, char,
boolean, or String. (These are the eight primitive types
plus the type String.) That is, you can say
"System.out.print(x);" or "System.out.println(x);",
where x is any expression whose value is of one of these types.
The expression can
be a constant, a variable, or even something more complicated
such as 2*distance*time.
In fact, there are actually several different subroutines to handle the different parameter types.
There is one System.out.print for printing values of
type double, one for values of type int, another for
values of type String, and so on. These subroutines can have the
same name since the computer can tell which one you mean in a given
subroutine call statement, depending on the type of parameter
that you supply. Having several subroutines of the same name that differ
in the types of their parameters is called overloading.
Many programming languages do not permit overloading, but it is common
in Java programs.
The difference between System.out.print and System.out.println
is that System.out.println outputs a carriage return after it outputs
the specified parameter value. There is a version of System.out.println
that has no parameters. This version simply outputs a carriage return, and
nothing else. Of course, a subroutine call statement for this version of
the program looks like "System.out.println();", with empty parentheses.
Note that "System.out.println(x);" is exactly equivalent
to "System.out.print(x); System.out.println();". (There is
no version of System.out.print without parameters. Do you see why?)
As mentioned above, the TextIO subroutines TextIO.put
and TextIO.putln can be used as replacements for System.out.print
and System.out.println. However, TextIO goes beyond System.out
by providing additional, two-parameter versions of put and putln.
You can use subroutine call statements of the form
"TextIO.put(x,n);" and "TextIO.putln(x,n);",
where the second parameter, n, is an integer-valued expression. The idea is
that n is the number of characters that you
want to output. If x takes up fewer than n
characters, then the computer will add some spaces at the beginning
to bring the total up to n. (If x already takes up
more than n characters, the computer will just print out more characters
than you ask for.) This feature is useful, for example, when
you are trying to output neat columns of numbers, and you know just
how many characters you need in each column.
The TextIO class is a little more versatile at doing
output than is System.out. However, it's
input for which we really need it.
With TextIO, input is done using functions.
For example, TextIO.getInt(), which was discussed above,
makes the user type in a value of type int and returns
that input value so that you can use it in your program.
TextIO includes several functions for reading different
types of input values. Here are examples of using each of them:
b = TextIO.getByte(); // value read is a byte
i = TextIO.getShort(); // value read is a short
j = TextIO.getInt(); // value read is an int
k = TextIO.getLong(); // value read is a long
x = TextIO.getFloat(); // value read is a float
y = TextIO.getDouble(); // value read is a double
a = TextIO.getBoolean(); // value read is a boolean
c = TextIO.getChar(); // value read is a char
w = TextIO.getWord(); // value read is a String
s = TextIO.getln(); // value read is a String
For these statements to be legal, the variables on the
left side of each assignment statement must be of
the same type as that returned by the function on
the right side.
When you call one of these functions, you are guaranteed
that it will return a legal value of the correct type.
If the user types in an illegal value as input -- for example, if
you ask for a byte and the user types in a number
that is outside the legal range of -128 to 127 -- then the
computer will ask the user to re-enter the value, and your
program never sees the first, illegal value that the user
entered.
You'll notice that there are two input functions that
return Strings. The first, getWord(), returns
a string consisting of non-blank characters only. When it
is called, it skips over any spaces and carriage returns typed
in by the user. Then it reads non-blank characters until it
gets to the next space or carriage return. It returns a String
consisting of all the non-blank characters that it has read.
The second input function, getln(), simply returns
a string consisting of all the characters typed in by the
user, including spaces, up to the next carriage return.
It gets an entire line of input text.
The carriage return itself is not returned as part of the
input string, but it is read and discarded by the computer.
Note that the String returned by this function might be
the empty string,
"", which contains no characters at all.
All the other input functions listed -- getByte(), getShort(),
getInt(), getLong(), getFloat(),
getDouble(), getBoolean(), and getChar() -- behave like
getWord(). That is, they will skip past
any blanks and carriage returns in the input before reading
a value. However,
they will not skip past other characters.
If you try to read two ints and the user types "2,3",
the computer will read the first number correctly, but when it
tries to read the second number, it will see the comma. It will
regard this as an error and will force the user to retype the number.
If you want to input several numbers from one line, you should
make sure that the user knows to separate them with spaces,
not commas. Alternatively, if you want to require a comma between
the numbers, use getChar() to read the comma before
reading the second number.
There is another character input function, TextIO.getAnyChar(),
which does not skip past blanks or carriage returns. It simply reads
and returns the next character typed by the user. This could be
any character, including a space or a carriage return. If the
user typed a carriage return, then the char returned
by getChar() is the special linefeed character '\n'.
There is also a function, TextIO.peek(), that
let's you look ahead at the next character in the input without
actually reading it. After you "peek" at the next
character, it will still be there when you read the next item
from input. This allows you to look ahead and see what's
coming up in the input, so that you can take different actions
depending on what's there.
The semantics of input is much more complicated than the
semantics of output. The first time the program tries to
read input from the user, the computer will wait while the
user types in an entire line of input. TextIO stores that line in
a chunk of internal memory called the input buffer. Input is
actually read from the buffer, not directly from the user's typing.
The user only gets to type when the buffer is empty. This lets
you read several numbers from one line of input. However, if you only
want to read in one number and the user types in extra stuff
on the line, then you could be in trouble. The extra stuff will still
be there the next time you try to read something from input. (The symptom of this
trouble is that the computer doesn't pause where you think it
should to let the user type something in. The computer had
stuff left over in the input buffer from the previous
line that the user typed.) To help you
avoid this, there are versions of the TextIO input functions
that read a data value and then discard any leftover stuff on
the same line:
b = TextIO.getlnByte(); // value read is a byte
i = TextIO.getlnShort(); // value read is a short
j = TextIO.getlnInt(); // value read is an int
k = TextIO.getlnLong(); // value read is a long
x = TextIO.getlnFloat(); // value read is a float
y = TextIO.getlnDouble(); // value read is a double
a = TextIO.getlnBoolean(); // value read is a boolean
c = TextIO.getlnChar(); // value read is a char
w = TextIO.getlnWord(); // value read is a String
Note that calling getlnDouble(), for example, is
equivalent to first calling getDouble() and then calling
getln() to read any remaining data on the same line,
including the end-of-line character itself.
I strongly advise you to use the "getln"
versions of the input routines, rather than the "get"
versions, unless you really want to read several items from
the same line of input.
You might be wondering why there are only two output routines,
put and putln, which can output data values of any
type, while there is a separate input routine for each data
type. As noted above, in reality there are many put
and putln routines. The computer can tell them apart
based on the type of the parameter that you provide. However,
the input routines don't have parameters, so the different
input routines can only be distinguished by having different names.
Using TextIO for input and output, we can now improve the
program from Section 2
for computing the value of an investment. We can
have the user type in the initial value of the investment
and the interest rate. The result is a much more useful
program -- for one thing, it makes sense to run more than once!
public class Interest2 {
/*
This class implements a simple program that
will compute the amount of interest that is
earned on an investment over a period of
one year. The initial amount of the investment
and the interest rate are input by the user.
The value of the investment at the end of the
year is output. The rate must be input as a
decimal, not a percentage (for example, 0.05,
rather than 5).
*/
public static void main(String[] args) {
double principal; // the value of the investment
double rate; // the annual interest rate
double interest; // the interest earned during the year
TextIO.put("Enter the initial investment: ");
principal = TextIO.getlnDouble();
TextIO.put("Enter the annual interest rate: ");
rate = TextIO.getlnDouble();
interest = principal * rate; // compute this year's interest
principal = principal + interest; // add it to principal
TextIO.put("The value of the investment after one year is $");
TextIO.putln(principal);
} // end of main()
} // end of class Interest2
Try out an equivalent applet here. (If the applet does not
respond to your typing, you might have to click on it to activate it.)
By the way, the applets on this page don't actually use TextIO. The
TextIO class is only for use in programs, not applets. For applets,
I have written a separate class that provides similar input/output capabilities
in a Graphical User Interface program.