The Scanner
Class
Because of the complications of the levels of hierarchy in the Files class, starting in Java 1.5, a new class was introduced, called the Scanner class. It is in the class java.util.Scanner, so to use it, one must have
import java.util.*;
inside the class which is using it. The Scanner class can only be used for text files (i.e., ASCII encoded files) to parse primitive data types (char, int, double, etc.). In general, it will read from the file byte by byte until it finds a whitespace. A whitespace is one of three characters: (1) blank space, (2) tab, or (3) a line feed. We refer to the data read in between whitespaces as tokens. (Note, for example, that three consecutive blank characters are considered to be just one whitespace.) You type in the line feed by hitting the Enter key on your keyboard.
The advantage of using an object of the Scanner class is that one only has to create it, and then one can read in data using the appropriate methods of the class. For example, if we have the data of the type in a file called Sample.txt:
widget 14 3.35
then the following code will read in it:
String name;
int units;
double price;
File inputFile = new File(“Sample.txt”);
Scanner input = new Scanner(inputFile);
Note that we can do this in one line with:
Scanner input = new Scanner(new File(“Sample.txt”));
name = input.next();
units = input.nextInt();
price = input.nextDouble();
The method next, reads in character by character as a char until it finds a whitespace. Similarly, nextInt reads in character by character (from the previous whitespace) until if finds a whitespace. (Note that three consecutive characters of whitespace are considered to be just one whitespace.) So for the above, name will have the value of “widget”, units the value of 14, and price the value of 3.35.
There are also methods in the Scanner class which allow you to see what the next input is without having to actually get it. E.g., one has a method hasNextInt which returns true if and only if the next token in the scanner’s input can be interpreted as an int. However, it does not actually get it.
You can also use the Scanner class to read in from the console window. Just as System.out is the reference to putting output to the console window, the System.in is the reference to getting input from the console window. Thus,
Scanner console = new Scanner(System.in);
int a,b;
System.out.print(“Give the first number: “);
a = console.nextInt();
System.out.print(“Give the second number: “);
b = console.nextInt();
System.out.print(“The sum of the two numbers given is “+ (a + b));
Then, when this program executes, at the console window, one would see the following:
Give the first number:
If one type in a 6, followed by the Enter key, the console window would look like:
Give the first number: 6
Give the second number:
Next, if one typed in a 51 and again hit the Enter key, the console window would look like:
Give the first number: 6
Give the second number: 51
The sum of the two numbers given is 57
This is because, when one typed in the first number 6, it was read in by the Scanner class object scan and stored in the variable a. The next time the object scan read in the number 51 and assigned it to b.
Note that if one had written for the last line the following:
System.out.print(“The sum of the two numbers given is “+ a + b);
The output would have been
The sum of the two numbers given is 651
Why is this so?
Note that if one does the following for the above:
Give the first number: 6
Give the second number: 3a
Then the line of
b = console.nextInt();
will not be able to convert the “3a” into an integer. The program will terminate at this point because an exception has happened. This type of exception is called a InputMismatchException by Java. It is called this because the input given in “3a” does not match the input expected, an “integer”.
Java incorporates a mechanism, known as exception
handling, to manage run-time errors that are detected by the Java Virtual
Machine, including those that result from illegal input. The term exception
refers to a run-time failure. It said that the program throws an
exception when it encounters a run-time error that is too severe to continue
normally. For example, a file security violation within a program results in an
exception. Similarly, when a program attempts to create a new file on a disk
that is already full, an exception is thrown.
The preferred way to deal with an
exception is a try instruction. A try instruction is a Java
statement that has a body, much the same way a method has a body. When the try
statement executes, its body executes. If no exceptions are thrown during the
execution of the try's body, then the catch clauses are ignored,
and execution proceeds as though there were no try instruction.
Every Java exception has some type, and
if an exception is thrown within a try body and if the exception has a
type matching one of the catch clauses, then the remainder of the try
body is skipped and the matching catch clause is executed.
If an exception is thrown and caught by
the appropriate catch clause, then after the catch clause finishes executing,
the next instruction to be executed is the first instruction after that
clause. That is to say, if one has:
try
{
…
a;
…
}
catch(…)
{
…
c;
}
b;
Suppose during the execution of
instruction a there is a run-time exception generated which is caught by
the catch phrase. After the execution of
instruction c, then next instruction to be executed is instruction b. Any instruction after a that is inside the try clause
is not executed. Instruction a is not
completed.
One handles the bad input above with the try…catch clause for exceptions. Thus, one would have the following code:
int a,b;
boolean goodData;
goodData = false;
while(!goodData)
{
try
{
System.out.print(“Give the first number: “);
a = console.nextInt();
goodData = true;
}
catch(InputMismatchException e)
{
//handle the exception here
System.out.println(“Bad input data, you must give an integer”);
}
}//end while loop
goodData = false;
while(!goodData)
{
try
{
System.out.print(“Give the second number: “);
b = console.nextInt();
goodData = true;
}
catch(InputMismatchException e)
{
//handle the exception here
System.out.println(“Bad input data, you must give an integer”);
}
}//end while loop
System.out.print(“The sum of the two numbers given is “+ (a + b));
This would be a robust way to make sure “good” data was input in and the program did not break. The reason that this works is as follows. Suppose that the input for the first number is 6, while the second number gives the input of 3a. Then for the first while clause, since the input is good data, the value of 6 is assigned to the variable a. Then the next line of goodData = true is executed. Since the exception is not generated, the catch clause is ignored and one terminates the body of the loop. As goodData has its value set to true, the while loop is finished.
For the second input, since 3a is input and it can not be converted into an integer, the flow of control jumps over the remaining lines of code (goodData = true;) and jumps to the catch clause. It outputs the System.out.println statement and finishes the body of the while loop (the next line after the catch clause). Then the while condition has not been satisfied (goodData is still false), so it re-enters the body of the loop and retries to get the second integer. It will remain inside the while loop until good data is input.
The console terminal would look like the following:
Give the first number: 6
Give the second number: 3a
Bad input data, you must give an integer
Give the second number: 51
The sum of the two numbers given is 57