Using Buffered Readers – Java I/O: Part I

Using Buffered Readers

A BufferedReader can be chained to the underlying reader by using one of the following constructors:

Click here to view code image

BufferedReader(Reader in)
BufferedReader(Reader in, int size)

The default buffer size is used, unless the buffer size is explicitly specified.

In addition to the methods of the Reader class, the BufferedReader class provides the method readLine() to read a line of text from the underlying reader.

Click here to view code image

String readLine() throws IOException

The null value is returned when the end of the stream is reached. The returned string must explicitly be converted to other values.

The BufferedReader class also provides the lines() method to create a stream of text lines with a buffered reader as the data source (§16.4, p. 902).

Stream<String> lines()

Returns a finite sequential ordered Stream of element type String, where the elements are text lines read by this BufferedReader.

The following code creates a BufferedReader that can be used to read text lines from a file (Figure 20.7(b)):

Figure 20.7 Buffered Readers

Click here to view code image

// Using the UTF-8 character encoding:
Charset utf8 = Charset.forName(“UTF-8”);
FileReader     fileReader      = new FileReader(“lines.txt”, utf8);
BufferedReader bufferedReader1 = new BufferedReader(reader)
// Use the default encoding:
FileReader     fileReader      = new FileReader(“lines.txt”);
BufferedReader bufferedReader2 = new BufferedReader(fileReader);

Note that in both cases the BufferedReader object is used to read the text lines.

Java primitive values and objects cannot be read directly from their text representation in a file. Characters must be read and converted to the relevant values explicitly. If the text representation of the values is written as lines of text, each line can be read and tokenized first—that is, grouping characters into tokens that meaningfully represent a value. For example, the line “Potatoes 2.50” contains two tokens: the item token “Potatoes” and the price token “2.50”. Once a line is tokenized, the tokens can be parsed to obtain the appropriate type of value. The item token is already of type String, but the price token “2.50” needs to be parsed to a double value using the Double.parseDouble() method. A scanner provided by the java.io.Scanner class or the String.split() method called on each line can be used to tokenize the character input—both of which are beyond the scope of this book.

In contrast to Example 20.2, which demonstrated the reading and writing of binary representations of primitive data values, Example 20.4 illustrates the reading and writing of text representations of values using I/O streams that are readers and writers.

The CharEncodingDemo class in Example 20.4 writes text representations of values using the UTF-8 character encoding specified at (1). It uses a try-with-resources statement for handling the closing of I/O streams, as shown at (2) and (4). The PrintWriter is buffered (Figure 20.6(b)). Its underlying writer uses the specified encoding, as shown at (2). Values are written out with the text representation of one value on each line, as shown at (3). The example uses the same character encoding to read the text file. A BufferedReader is created (Figure 20.7(b)). Its underlying reader uses the specified encoding, as shown at (4). The text representation of the values is read as one value per line, and parsed accordingly. Each text line in the file is read by calling the readLine() method. The characters in the line are explicitly converted to an appropriate type of value, as shown at (5).

The values are printed on the standard output stream, as shown at (6). We check for the end of the stream at (7), which is signaled by the null value returned by the readLine() method of the BufferedReader class. Note the exceptions that are specified in the throws clause of the main() method.

Although buffering might seem like overkill in this simple example, for efficiency reasons, it should be considered when reading and writing characters from external storage.

It is a useful exercise to modify Example 20.4 to use the various setups for chaining streams for reading and writing characters, as outlined in this section.

Example 20.4 Demonstrating Readers and Writers, and Character Encoding

Click here to view code image

import java.io.*;
import java.nio.charset.Charset;
import java.time.LocalDate;
public class CharEncodingDemo {
  public static void main(String[] args)
         throws FileNotFoundException, IOException, NumberFormatException {
    // UTF-8 character encoding.
    Charset utf8 = Charset.forName(“UTF-8”);                           // (1)
    try(// Create a BufferedWriter that uses UTF-8 character encoding     (2)
        FileWriter writer = new FileWriter(“info.txt”, utf8);
        BufferedWriter bufferedWriter1 = new BufferedWriter(writer);
        PrintWriter printWriter = new PrintWriter(bufferedWriter1, true);) {
      System.out.println(“Writing using encoding: ” + writer.getEncoding());
      // Print some values, one on each line.                             (3)
      printWriter.println(LocalDate.now());
      printWriter.println(Integer.MAX_VALUE);
      printWriter.println(Long.MIN_VALUE);
      printWriter.println(Math.PI);
    }
    try(// Create a BufferedReader that uses UTF-8 character encoding     (4)
        FileReader reader = new FileReader(“info.txt”, utf8);
        BufferedReader bufferedReader = new BufferedReader(reader);) {
      System.out.println(“Reading using encoding: ” + reader.getEncoding());
      // Read the character input and parse accordingly.                  (5)
      LocalDate ld = LocalDate.parse(bufferedReader.readLine());
      int iMax = Integer.parseInt(bufferedReader.readLine());
      long lMin = Long.parseLong(bufferedReader.readLine());
      double pi = Double.parseDouble(bufferedReader.readLine());
      // Write the values read on the terminal                            (6)
      System.out.println(“Values read:”);
      System.out.println(ld);
      System.out.println(iMax);
      System.out.println(lMin);
      System.out.println(pi);
      // Check for end of stream:                                         (7)
      String line = bufferedReader.readLine();
      if (line != null ) {
        System.out.println(“More input: ” + line);
      } else {
        System.out.println(“End of input stream”);
      }
    }
  }
}

Output from the program:

Writing using encoding: UTF8
Reading using encoding: UTF8
Values read:
2021-06-22
2147483647
-9223372036854775808
3.141592653589793
End of input stream

Leave a Reply

Your email address will not be published. Required fields are marked *