Section 4.6 From the Java Library: java.io.File
and File Input (Optional)
In addition to command-line and GUI user interfaces, there is one more standard user interface, files. In this section we show how the Scanner
class, that was used in ChapterĀ 2 for keyboard input, can also read input from files. Reading input from a file is relevant to only certain types of programming problems. It is hard to imagine how a file would be used in playing the One Row Nim game but a file might very well be useful to store a collection of riddles that could be read and displayed by a Java program. We will develop such a program later in this section.
Java has two types of files, text files and binary files. A text file stores a sequence of characters and is the type of file created by standard text editors like NotePad and WordPad on a Windows computer or SimpleText on a Macintosh. A binary file has a more general format that can store numbers and other data the way they are
stored in the computer. In this section we will consider only text files. Binary files are considered in ChapterĀ 11.
Subsection 4.6.1 File Input with the File
and Scanner
Classes
An instance of the java.io.File
class stores information that a Scanner
object needs to create an input stream that is connected to the sequence of characters in a text file. A partial list of the public methods of the File
class is given in the UML class diagram in FigureĀ 4.26. We will need to use only the File()
constructor in this section. The File
instance created with the statement
File theFile = new File("riddles.txt");
will obtain and store information about the "riddles.txt" file in the same directory as the java code being executed, if such a file exists. If no such file exists, the File
object stores information needed to create such a file but does not create it. In ChapterĀ 11, we will describe how other objects can use a file object to create a file in which to write data. If we wish to create a File
object that describes a file in a directory other than the one containing the Java program, we must call the constructor with a string argument that specifies the file's complete path nameāthat is, one that lists the sequence of directories containing the file. In any case, while we will not use it at this time, the exists()
method of a File
instance can be used to determine whether or not a file has been found with the specified name.
In order to read data from a file with a Scanner
object we will need to use methods that were not discussed in ChapterĀ 2. An expanded list of methods of the Scanner
class is given in FigureĀ 4.27. Note the there is a Scanner()
constructor with a File
object as an argument. Unlike the other create()
method that was used in ChapterĀ 2, this create()
throws an exception that must be handled. The following code will create a Scanner
object that will be connected to an input stream that can read from a file:
try
{ File theFile = new File("riddles.txt");
fileScan = new Scanner(theFile);
fileScan = fileScan.useDelimiter("\r\n");} catch (IOException e)
{ e.printStackTrace();} //catch()
We will discuss the try-catch
commands when exceptions are covered in ChapterĀ 10. Until then, the try-catch
structures can be copied exactly as above, if you wish to use a Scanner
object for file input. In the code above, the useDelimiter()
method has been used to set the Scanner
object so that spaces can occur in strings that are read by the Scanner
object. For the definition of a class to read riddles from a file, the above code belongs in a constructor method.
After we create a Scanner
object connected to a file, we can make a call to nextInt()
, nextDouble()
, or next()
method to read, respectively, an integer, real number, or string from the file. Unlike the strategy for using a Scanner
object to get keyboard input, it is suggested that you test to see if there is more data in a file before reading it. This can be done with the hasNext()
, hasNextInt()
, and hasNextDouble()
methods. These methods return the value true
if there are more data in the file.
The program in FigureĀ 4.6.1 is the complete listing of a class that reads riddles from a file
and displays them. Note that, in the body of the method readRiddles()
, the statements:
String ques = null;
String ans = null;
Riddle theRiddle = null;
make explicit the fact that variables that refer to objects are assigned null
as a value when they are declared. The statements:
if (fileScan.hasNext())
ques = fileScan.next();
if (fileScan.hasNext())
{ ans = fileScan.next();
theRiddle = new Riddle(ques, ans);}
will read String
s into the variables ques
and ans
only if the file contains lines of data for them. Otherwise the readRiddle()
method will return a null
value. The main()
method uses this fact to terminate a while
loop when it runs out of string data to assign to Riddle
questions and answers. There is a separate method, displayRiddle()
using a separate instance of Scanner
attached to the keyboard to display the question of a riddle before the answer.
The contents of the "riddles.txt" file should be a list of riddles with each question and answer on a separate line. For example The following three riddles saved in a text file would form a good example to test the RiddleFileReader
class.
What is black and white and red all over?
An embarrassed zebra
What is black and white and read all over?
A newspaper
What other word can be made with the letters of ALGORITHM?
LOGARITHM
When the main()
method is executed, the user will see output in the console window that looks like:
What is black and white and red all over?
Input any letter to see answer: X
An embarrassed zebra
What is black and white and read all over?
Input any letter to see answer:
Files are covered in depth in ChapterĀ 11. Information on writing data to a file and reading data from a file without using the Scanner
class can be found in that chapter.
Subsection 4.6.2 Self-Study Exercises
Modify the
RiddleFileReader
class to create a programNumberFileReader
that opens a file named "numbers.txt" and reports the sum of the squares of the integers in the file. Assume that the file "numbers.txt" contains a list of integers in which each integer is on a separate line. The program should print the sum of the squares in theSystem.out
console window. In this case, there is no need to have a method to display the data being read or aScanner
object connected to the keyboard. You will want a constructor method and a method that reads the numbers and computes the sum of squares.