We’ve already been reading data from files throughout most of this course. However, let’s take some time to review that code and improve it a bit to make it more flexible for use in the future.
Opening a File using java.nio.file
Here is the code we’ve used in the Exceptions module to open a file for reading:
reader = new Scanner(new File("input.txt""));
This code uses a file name "input.txt"
, and then creates a Scanner object to read data from that file, using an intermediate File object to represent the file itself. Scanners only open files for reading.
The File object used here is part of the older java.io
package, which has been present in the Java API for quite a while. However, more recent versions of Java have included the new java.nio.file
package, which includes many easier to use methods for handling files and directories.
So, instead of using a File object from java.io
, we will use a Path object from java.nio.file
, which is much more flexible. In fact, it is completely compatible with the older versions, so we can easily obtain a Path from a File and vice-versa.
To create a Path object, we use the Paths.get()
static method. So, an updated version of our starter code might look like this:
import java.util.Scanner;
import java.nio.file.Paths;
public class Read{
public static void main(String[] args) throws Exception{
Scanner reader;
reader = new Scanner(Paths.get("input.txt"));
/* -=-=-=-=- MORE CODE GOES HERE -=-=-=-=- */
}
}
There are a couple of important changes:
- Instead of
import java.io.File;
at the top of the code, we must now useimport java.nio.file.Paths;
to get access to the new Paths class. - When creating the Scanner, we can now use
reader = new Scanner(Paths.get("input.txt"));
. This will use thePaths.get()
static method to create a Path object, and then use that object to construct a Scanner which can read data from the file found at that path.
With those changes in place, we are now using the java.nio.file
library, which we’ll use throughout this chapter.
Exceptions
Of course, as we learned in an earlier chapter, we should also add some Try-Catch and Try with Resources statements to this code to prevent any exceptions. So, let’s do that now:
import java.util.Scanner;
import java.nio.file.Paths;
import java.lang.ArrayIndexOutOfBoundsException;
import java.nio.file.InvalidPathException;
import java.nio.file.NoSuchFileException;
public class Read{
public static void main(String[] args) throws Exception{
try(
//Try with Resources will automatically close the file
Scanner scanner = new Scanner(Paths.get("input.txt"));
){
/* -=-=-=-=- MORE CODE GOES HERE -=-=-=-=- */
//add additional catch statements here to handle expected exceptions
}catch(InvalidPathException e){
//path is invalid
System.out.println("Error: invalid file path!");
return;
}catch(NoSuchFileException e){
//file is not found
System.out.println("Error: file not found!");
return;
}catch(Exception e){
//generic catch statement
System.out.println("Error: unknown error while reading input!");
}
}
}
This code is very similar to the code we saw in a previous chapter, with a couple of major changes:
- At the bottom, we are using a Try with Resources statement to actually handle reading our input. This will automatically close the file once we are done with it. Otherwise, we’d need to add
scanner.close()
at the end of our program, possibly in afinally
block. - Since we are using the
java.nio.file
package, we now must useimport java.nio.file.NoSuchFileException;
to get the correct exception when a file cannot be found. - In addition, the
Paths.get()
method can throw anInvalidPathException
if the path provided cannot be converted to a proper path.
Reading Data
Once we have our file open, we can use the same methods we’ve been using to read data from the file. For example, we can use a simple While loop to read each line of the file:
while(scanner.hasNext()){
String line = scanner.nextLine().trim();
if(line.length() == 0){
break;
}
}
In this code, we use the hasNext()
method to check and see if the file has any additional lines to read. If so, it will read the line using the nextLine()
method. We are also using the trim()
method to remove any extra spaces from the beginning and end of the line. Finally, we have a short If-Then statement to check and see if the line is empty. If so, we’ll assume that we’ve reached the end of the input file, or that the user typing input via the terminal is done, and we’ll break
out of the loop.