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 is not even implemented in some Java programming environments, such as CodeWarrior 11 on the Macintosh.)

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, better support is needed for input/output in old-fashioned non-GUI programs. Fortunately, is possible to extend Java by creating new classes that provide subroutines that are not already built into Java. If your program has access to a class created by you or by someone else, you can use the routines defined in that class in your program. You don't even have to understand the details of how they work. This is, of course, the whole idea behind building on and reusing previous work.

For example, I've written a class called TextIO that defines subroutines for reading values input by the user. The subroutines in this class make it possible to get input from the standard input object, System.in, without knowing about certain advanced aspects of Java that you would need to know to use System.in directly. TextIO also has a set of output procedures that slightly augment the abilities of System.out.

To use the TextIO class, you must make sure that the class is available to your program. (This means putting the compiled file, TextIO.class, in the same directory with your main program class. If you are using a programming environment such as Visual J++, you could also just add the source code file, TextIO.java, to your programming project.) Let's assume that you've made TextIO available to your program and that you want to use it to read an integer typed in by the user. The value that the user types in is to be stored in a variable named userInput of type int. Assuming that userInput is declared earlier in the program, you could do this with the assignment statement:

userInput = TextIO.getInt()

When the computer executes this statement, it will wait for the user to type in an integer value and then it will store that value in the variable named userInputTextIO.getInt() is a subroutine that tells the computer to read an integer typed by the user. For output, TextIO includes TextIO.put() and TextIO.putln(), which can be used in place of System.out.print() and System.out.println().

Here, for example, is a complete program that prints out the square of a number typed by the user:

                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
                     
                     TextIO.put("Please type a number: ");
                     userInput = TextIO.getInt();
                     square = userInput * userInput;
                     TextIO.put("The square of that number is ");
                     TextIO.putln(square);
                     
                  } // end of main()
                  
                } //end of class PrintSquare

In the remainder of this chapter and in the next chapter, I will use TextIO for input and output in all my examples. Keep in mind that TextIO can only be used in a program if TextIO.class is available to that program.


The TextIO routines put() and putln() are used for writing values to standard output. You can say "TextIO.put(x);" or "TextIO.putln(x);" where "x" is any expression whose value is of type byte, short, int, long, float, double, char, boolean, or String. The expression can be a constant, a variable, or even something more complicated such as 2*distance*time. The difference between put and putln is that putln adds a carriage return at the end of the output. If you use TextIO.put(x), then the next item that is output will follow the value of x on the same line.

If you want to output a carriage return, with no other output, you can say "TextIO.putln();", with nothing between the parentheses. Note that "TextIO.putln(x)" is exactly equivalent to "TextIO.put(x); TextIO.putln();".

Finally, I will note briefly that you can also do output using "TextIO.put(x,n);" and "TextIO.putln(x,n);", where 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, there's not much that the computer can do. It will just have to 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 that we really need it for.

For input, the TextIO class uses functions. A function is a subroutine that returns a value. A function call can be used as part of an expression; often, though, the value is simply assigned to a variable. Here are examples of using all the input functions defined for objects of type TextIO:

         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 that is 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. 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.

The character input function getChar() 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 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.)

All the other input functions -- getByte(), getShort(), getInt(), getLong(), getFloat(), getDouble(), and getBoolean() -- will skip past any blanks and carriage returns that the user types. 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.

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, but 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 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 has read 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. It's a good idea 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 out data values of any type, while there is a separate input routine for each data value. The reason is that put and putln are used in the form TextIO.put(x) and TextIO.putln(x) with a parameter, x. The computer knows what type of value x is. The input functions, on the other hand, don't have parameters. So you have to tell the computer explicitly what type of value it is supposed to read.


Using TextIO for input and output, we can now improve our program 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 -- our first example program that it makes sense to run more than once!

            public class Interest3 {
            
            /*
               This class implements a simple program that
               will compute the amount of interest that is
               earned on an investment over a period of
               5 years.  The initial amount of the investment
               and the interest rate are input by the user.
               The value of the investment at the end of each
               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
                
                TextIO.put("Enter the initial investment: ");
                principal = TextIO.getlnDouble();
                
                TextIO.put("Enter the annual interest rate: ");
                rate = TextIO.getlnDouble();
                
                int years = 0;  // counts the number of years that have passed
                
                while (years < 5) {
                   double interest = principal * rate;   // compute this year's interest
                   principal = principal + interest;     // add it to principal
                   years = years + 1;    // count the current year.
                   if (years > 1) {
                      TextIO.put("The value of the investment after ");
                      TextIO.put(years);
                      TextIO.put(" years is $");
                   }
                   else {
                      TextIO.put("The value of the investment after 1 year is $");
                   }
                   TextIO.putln(principal);
                } // end of while loop
                
            } // end of main()
               
         } // end of class Interest3
         

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.)

Sorry, your browser doesn't
support Java.

By the way, this applet does not actually use TextIO. The TextIO class is only for use in programs, not applets. I'll tell you more about how the sample applets were written in Section 6.


[ Next Section | Previous Section | Chapter Index | Main Index ]