Scanning Files

Reading the Documentation

First, let’s look at the Java documentation for the Scanner class. Java has great documentation for all its built-in libraries, and it is the first place you should look when you are trying to figure out how to do something. Take a look at the Scanner documentation here.

There’s a lot of information on that page, but what you should be most interested in is the writeup at the top about how to use Scanner, and then the list of all the Scanner methods. Look at the documentation for hasNext() and next(). Note that they behave like hasNextInt() and nextInt(), except they read and return strings. You should also notice that Scanner has hasNext and next methods for a variety of types.

Using Scanner with words

In VS Code, open the file Words.java. Copy the code from Numbers.java into Words.java.

Change the code so that rather than scanning for numbers, the scanner returns words. To do this, change String numbers = "..." to String words = "Java is very wordy!" and replace hasNextInt() and nextInt() with hasNext() and next(), respectively. (You will also have to change the type of the variable that holds the return value from next, since it’s now returning a String and not an int.)

Compile and run your code.

Using Scanners with Files

Next, you’ll change your code to not read from a fixed string, but from a file. Below is some example code that creates a Scanner that reads from a file named input.txt. (You will note that we have provided you with an input.txt file with the lab files.)

Note that you need a try/catch around where you create the new Scanner because the file may not exist. In order to have the Scanner exist outside the try/catch blocks, you will need to declare it before you initialize it. We will declare it and set it to null above the block, and then set it equal to a new Scanner that takes in a File object. If the file does not exist, we will exit the program using System.exit()

// We need to declare scanner outside the try/catch block so that it is in scope
// when we use it in our loop.
Scanner scanner = null;
try {
    scanner = new Scanner(new File("input.txt")); 
} catch (FileNotFoundException e) {
    System.out.println("Problem opening file: " + e.getMessage());
    System.exit(1);
}

Copy this code into Words.java to replace where you previously created your scanner. Leave the rest of the while loop the same.

This code uses two new Java libraries: File and FileNotFoundException. We need to add import statements so that Java knows we’re using these libraries. Add these import lines at the top of the file next to your other import line.

import java.io.File;
import java.io.FileNotFoundException;

Save your work and then compile and run Words.

Using Multiple Scanners to Preserving Spacing

Notice that the previous code put every word on a line of its own. That’s not great. Change System.out.println() to use System.out.print() instead and compile and run. What do you think will happen? Try it out.

Okay, that’s not great. Try printing out a space after each word. You can do it via something like this.

String word = scanner.next();
System.out.print(word + " ");

Save and then compile and run.

That’s better, but we still lost all of the line breaks!

We can solve this by using multiple scanners. Rather than using scanner.hasNext() and scanner.next(), we can use scanner.hasNextLine() and scanner.nextLine(). Each call to scanner.nextLine() will return a string containing a line of the file. We will then use a second scanner to scan that string.

Inside your while loop, create a new scanner that will scan the line. Your code might look something like this. (Note that in this example we’ve renamed our original scanner to lineScanner, and added a new scanner, wordScanner.)

while (lineScanner.hasNextLine()) {
    String line = lineScanner.nextLine();
    Scanner wordScanner = new Scanner(line);
    // other code here
    wordScanner.close();
}
lineScanner.close();

Print out each word in each line using System.out.print() with appropriate spaces between words. At the end of each line, print a new line via

System.out.println();

Remember to add, commit, and push your changes to GitHub!