Page 645 - Introduction to Programming with Java: A Problem Solving Approach
P. 645
Scanner’s hasNextLine method provides a convenient loop-termination signal when you’re read- ing data with Scanner’s nextLine method. Looping stops automatically at the end of the file when there are no more lines to read. You can use the program in Figure 15.5 to read either the text in Figure 15.4a or the numbers in Figure 15.4b. It works for the numbers as well as the text because the program just prints the numbers and spaces between them as it reads them—as sequences of characters—without bothering to interpret the meanings of those sequences of characters.
Instead of reading a full line at a time, you could use Scanner’s hasNext method as a loop termina- tion signal and then read data with Scanner’s next method. The next method reads one token at a time. A token is a sequence of characters separated from preceding and subsequent sequences by whitespace. Said another way, a token is an isolated word or number. Whether you read a line at a time or a token at a time, it’s hard to fail at reading pure text!
It’s a different story, however, if the program needs to know the numerical values of numbers in a text file. If the text file has whitespace between adjacent numbers, the computer can read those numbers and si- multaneously parse them (determine their numerical values) by using Scanner methods like nextInt or nextDouble. These methods throw unchecked exceptions if parsing errors occur. If you want to enhance the program in Figure 15.5 to include numerical parsing, you might want to catch the unchecked exceptions thrown by parsing errors.
Reading Formatted Data in a Text File
If you want to use Scanner’s nextInt or nextDouble to parse numerical data as it is input, you must use whitespace to make each number a separate token. It is not abso-
15.4 Text-File Input 611
Use knowledge of format.
Apago PDF Enhancer
lutely necessary, however, to use whitespace to separate items in a text file. Instead, you
can keep track of the character position of the start and end of each item. That’s what was done in the days of old. For example, suppose each line in the file is formatted into three fields, like this:
columns 0–20 hold a String that might contain more than one word columns 21–28 hold the text representation of an int
columns 30–42 hold the text representation of a double.
To read the three fields, you should declare these three variables:
String text;
int iNum;
double dNum;
Read each line in as pure text, and then parse it, like this:
...
line = in.nextLine();
text = line.substring(0,21);
iNum = Integer.parseInt(line.substring(21,29).trim());
dNum = Double.parseDouble(line.substring(30,43).trim());
As you might recall, substring’s second argument is one greater than the index of the last character in the substring that is to be extracted. So in the above code fragment’s third statement, 29 is one greater than the int field’s last column.