A File object encapsulates the properties of a file or a path , but does not contain the methods for reading/writing data from/to a file. In order to perform I/O, you need to create objects using appropriate Java I/O classes. The objects contain the methods for reading/writing data from/to a file. This section introduces how to read/write strings and numeric values from/to a text file using the Scanner and PrintWriter classes.
The java.io.PrintWriter class can be used to write data to a text file. First, you have to create a PrintWriter object for a text file as follows :
PrintWriter output = new PrintWriter(filename);
Then, you can invoke the print , println , and printf methods on the PrintWriter object to write data to a file. Figure 8.14 summarizes frequently used methods in PrintWriter .
Listing 8.6 gives an example that creates an instance of PrintWriter and writes two lines to the file "scores.txt". Each line consists of first name (a string), middle name initial (a character), last name (a string), and score (an integer).
Lines 3 “7 check whether the file scores.txt exists. If so, exit the program (line 6).
Invoking the constructor new PrintWriter(String filename) will create a new file if the file does not exist. If the file already exists, the current content in the file will be discarded.
Invoking the constructor new PrintWriter(String filename) may throw an I/O exception. Java forces you to write the code to deal with this type of exception. You will learn how to handle it in Chapter 17, "Exceptions and Assertions." For now, simply declare throws Exception in the method declaration (line 2).
You have used the System.out.print and System.out.println methods to write text to the console. System.out is a standard Java object for the console. You can create objects for writing text to any file using print , println , and printf (lines 13 “16).
The close() method must be used to close the file. If this method is not invoked, the data may not be saved properly in the file.
The java.util.Scanner class was used to read strings and primitive values from the console in §2.13, "Console Input using the Scanner Class." A Scanner breaks its input into tokens delimited by whitespace characters . To read from the keyboard, you create a Scanner for System.in , as follows:
Scanner input = new Scanner(System.in);
To read from a file, create a Scanner for a file, as follows:
Scanner input = new Scanner(new File(filename));
Figure 8.15 summarizes frequently used methods in Scanner .
Listing 8.7 gives an example that creates an instance of Scanner and reads data from the file "scores.txt".
Note that new Scanner(String) creates a Scanner for a given string. To create a Scanner to read data from a file, you have to use the java.io.File class to create an instance of the File using the constructor new File(filename) (line 4), and use new Scanner(File) to create a Scanner for the file (line 7).
Invoking the constructor new Scanner(File) may throw an I/O exception. So the main method declares throws Exception in line 2.
Each iteration in the while loop reads first name, mi, last name, and score from the text file (lines 10 “17). The file is closed in line 20.
It is not necessary to close the input file (line 20), but it is a good practice to do so to release the resources occupied by the file.
Note
By default, the delimiters for separating tokens in a Scanner are whitespace. You can use the useDelimiter(String regex) method to set a new pattern for delimiters. |
Write a class named ReplaceText that replaces a string in a text file with a new string. The filename and strings are passed as command-line arguments as follows:
java ReplaceText sourceFile targetFile oldString newString
For example, invoking
java ReplaceText FormatString.java t.txt StringBuilder StringBuffer
replaces all the occurrences of StringBuilder by StringBuffer in FormatString.java and saves the new file in t.txt .
Listing 8.8 gives the solution to the problem. The program checks the number of arguments passed to the main method (lines 7 “11), checks whether the source and target files exist (lines 14 “25), creates a Scanner for the source file (line 28), creates a PrintWriter for the target file, and repeatedly reads a line from the source file (line 32), replaces the text (line 33), and writes a new line to the target file (line 34). You must close the output file (line 38) to ensure that data is saved to the file properly.
1 import java.io.*; 2 import java.util.*; 3 4 public class ReplaceText { 5 public static void main(String[] args) throws Exception { 6 // Check command line parameter usage 7 if (args.length != 4 ) { 8 System.out.println( 9 "Usage: java ReplaceText sourceFile targetFile oldStr newStr" ); 10 System.exit( ); 11 } 12 13 // Check if source file exists 14 File sourceFile = new File(args[ ]); 15 if ( !sourceFile.exists() ) { 16 System.out.println( "Source file " + args[ ] + " does not exist" ); 17 System.exit( ); 18 } 19 20 // Check if target file exists 21 File targetFile = new File(args[ 1 ]); 22 if ( targetFile.exists() ) { 23 System.out.println( "Target file " + args[ 1 ] + " already exists" ); 24 System.exit( ); 25 } 26 27 // Create input and output files 28 Scanner input = new Scanner(sourceFile); 29 PrintWriter output = new PrintWriter(targetFile); 30 31 while ( input.hasNext() ) { 32 String s1 = input.nextLine(); 33 String s2 = s1.replaceAll(args[ 2 ], args[ 3 ]); 34 output.println(s2); 35 } 36 37 input.close(); 38 output.close(); 39 } 40 } |
Pedagogical Note
The previous edition of this book introduced text I/O using many subclasses of java. io.Writer and java.io.Reader . These classes are lower-level and difficult to learn. The new features in java.io.PrinterWriter and java.util.Scanner classes are sufficient for all text I/O needs. For this reason, the old-style text I/O is now moved to Supplement VI.B, "Text I/O Using Reader and Writer ." |