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 you would need to know 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 PrintSquareHere'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.)
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 StringFor 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 StringNote 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 value. 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 Interest2Try 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.
[ Next Section | Previous Section | Chapter Index | Main Index ]