Aqua Phoenix
     >>  Lectures >>  Java 6  
 

Navigator
   
 
       
   

6.3 Text Files: Reading and Writing

Text file reading and writing is performed by creating file streams, and then reading and writing from and to those sequential streams. FileReader and FileWriter are particularly useful for text files, also called character streams.

6.3.1 FileReader

To create a file stream for reading a file, use the FileReader object:

File file = new File("someFile.txt");
try {
  FileReader fileReader = new FileReader(file);
} catch (Exception e) {
  e.printStackTrace();
}
or

try {
  FileReader fileReader = new FileReader(new File("someFile.txt"));
} catch (Exception e) {
  e.printStackTrace();
}
FileReader inherits from a more general class, called Reader. Reader defines methods for reading character streams into arrays of type char. It is then possible to read characters into an array of characters, one chunk at a time:

try {
  FileReader fileReader = new FileReader(new File("someFile.txt"));
  char[] c = new char[1024];
  int charRead;
  while ((charRead = fileReader.read(c)) > -1) {
    System.out.println(new String(c));
  }
  fileReader.close();
} catch (Exception e) {
  e.printStackTrace();
}

6.3.2 BufferedReader

Java also includes objects that encapsulate this relatively low-level operation, and provide methods for reading lines, one at a time. The operation of reading text files line-by-line is so common, that the design decision to create an additional layer made sense.

try {
  File file = new File("someFile.txt");
  FileReader fileReader = new FileReader(file);
  BufferedReader bufferedReader = new BufferedReader(fileReader);
} catch (Exception e) {
  e.printStackTrace();
}
or

try {
  BufferedReader bufferedReader = new BufferedReader(new FileReader(new File("someFile.txt")));
} catch (Exception e) {
  e.printStackTrace();
}
To read from a buffered stream, class BufferedReader provides the necessary methods. Besides reading arrays of characters, which was possible by using the FileReader by itself, it is now possible to read complete lines of text:

try {
  BufferedReader bufferedReader = new BufferedReader(new FileReader(new File("someFile.txt")));
  String line;
  while ((line = bufferedReader.readLine()) != null) {
    System.out.println(line);
  }
  bufferedReader.close();
} catch (Exception e) {
  e.printStackTrace();
}

6.3.3 FileWriter

FileWriter works similar to FileReader, only in the opposite direction.

To create a file stream for writing a file, use the FileWriter object:

try {
  FileWriter fileWriter = new FileWriter(file);
} catch (Exception e) {
  e.printStackTrace();
}
FileWriter inherits from the more general class Writer. Writer defines methods for writing characters and character arrays to a file. In the following example, we write individual characters into a new file. Since characters are encoded by integers (ASCII table), it is possible to write integers. More specifically, we write the alphabet in uppercase and lowercase letters, including some additional characters.

try {
  FileWriter fileWriter = new FileWriter(new File("newFile.txt"));
  for (int i = 65; i < 127; i++) {
    fileWriter.write(i);
  }
  fileWriter.close();
} catch (Exception e) {
  e.printStackTrace();
}

6.3.4 BufferedWriter

As with BufferedReader, there exists a more intuitive object for writing String of text (as opposed to character arrays).

try {
  BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(new File("newFile.txt")));
} catch (Exception e) {
}
Using this class, it is possible to write character arrays, characters, and Strings:

try {
  BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(new File("newFile.txt")));
  bufferedWriter.write("Hello World");
  bufferedWriter.close();
} catch (Exception e) {
  e.printStackTrace();
}

6.3.5 PrintWriter

There exists another encapsulation object, specifically designed for writing to text files. The PrintWriter extends the functionality of the BufferedWriter and allows writing primitive data types (int, double, float, etc.) without converting them to characters first.

try {
  PrintWriter printWriter = new PrintWriter(new BufferedWriter(new FileWriter(new File("newFile.txt"))));
} catch (Exception e) {
  e.printStackTrace();
}
To print a variety of primitives, simply use methods print() or println():

try {
  PrintWriter printWriter = new PrintWriter(new BufferedWriter(new FileWriter(new File("newFile.txt"))));
  printWriter.print(10);
  printWriter.print(86.34F);
  printWriter.print(82747.23873D);
  printWriter.println(10);
  printWriter.println(86.34F);
  printWriter.println(82747.23873D);
  printWriter.close();
} catch (Exception e) {
  e.printStackTrace();
}

6.3.6 Notes

  • File streams are sequential. When reading from them, a buffer of characters is returned, and the position of the reader is advanced to the next available character. While it is possible to seek to a specific position in a file, files tend to be read character-by-character or chunk-by-chunk, without explicit calls necessary for going to the next character or chunk.
  • Similarly, writing to an open file appends a string to the end of the file.
  • It is absolutely necessary to use the method close() once writing is complete. If this method is not called, the written file may not contain the last chunk of data. When file writing takes place, disk I/O is not performed for each character. This would be far to expensive (slow). Instead, a buffer of characters is filled, and then written. If method close() is not called, the remaining contents of the buffer will not be written, and hence the file is incomplete.
  • File I/O incorporates a large amount of exception handling. There are many things that can go wrong during reading or writing, including:
    • File doesn't exist
    • File can't be read or written to
    • Disk is full
    • Hard drive crashes
    • File is already open
    • etc.

    It is possible to catch individual exceptions, but it is also possible to catch the generic Exception instead, and print out an appropriate error message.