Skip to content

Java Input and Output


No matter where the data is coming from or going to and no matter what its type, the algorithms for sequentially reading and writing data are basically the same:

  • Reading
    • open a stream
    • while more information
      • read information
    • close the stream
  • Writing
    • open a stream
    • while more information
      • write information
    • close the stream

The java.io package contains a collection of stream classes that support these algorithms for reading and writing. To use these classes, a program needs to import the java.io package. The stream classes are divided into two class hierarchies, based on the data type (either characters or bytes) on which they operate.

Character Streams

Reader and Writer are the abstract superclasses for character streams in java.io. Reader provides the API and partial implementation for readers - streams that read 16-bit characters and Writer provides the API and partial implementation for writers—streams that write 16-bit characters. Subclasses of Reader and Writer implement specialized streams and are divided into two categories: those that read from or write to data sinks (shown in gray in the following figures) and those that perform some sort of processing (shown in white). The figure shows the class hierarchies for the Reader and Writer classes Most programs should use readers and writers to read and write textual information. The reason is that they can handle any character in the Unicode character set, whereas the byte streams are limited to ISO-Latin-1 8-bit bytes.

Reader Class Hierarchy

Writer Class Hierarchy

Using Streams - Input

The most common way to read from a file on disk:

This works just fine:

FileReader reader = new FileReader("testFile.txt");

BufferedReader in = new BufferedReader(reader);

This is usually coded like this, in nested constructors:

BufferedReader  in = new BufferedReader(new FileReader("testFile.txt"));

However! There’s an issue. This code won’t compile because the compiler requires exception handling. Wha? Let’s look at the Java API for these constructors.

public void run() {
    BufferedReader  in = new BufferedReader(new FileReader("testFile.txt"));
}

Java SE 8 API

OK, we’re back. So, how do we code this? If the compiler requires it, we have to do it. We’ll look at exception handling more a bit later. We also need to declare the BufferedReader out of the try so it can be closed in the finally block.

BufferedReader inputReader = null;
try {
    inputReader = new BufferedReader(new FileReader("testFile.txt"));

    // code to process the input file

} catch (FileNotFoundException fileNotFound) {
    System.out.println("There was a problem finding the file.");
    fileNotFound.printStackTrace();
} catch (IOException inputOutputException) {
    System.out.println("There was a problem reading the file.");
    ioException.printStackTrace();
} catch (Exception exception) {
    System.out.println("There was a problem.");
    exception.printStackTrace();
} finally {
    try {
        if (inputReader != null) {
            inputReader.close();
        }
    } catch (Exception exception) {
        System.out.println("There was a problem closing the BufferedReader.");
        exception.printStackTrace();
    }
}

Once the file is opened you will need to read the contents. We do this in a loop and read one line at a time. Here’s what the while loop will look like. (This will go inside the try block above.)

while (inputReader.ready()) {
    // read each line in here
}

Each line of the file is read with this code.

// Declare a String variable to hold the current line
    String line = null;

//  ...    

// Inside the while loop
    line = inputReader.readLine();

Put it all together and you get this.

BufferedReader inputReader = null;
try {
    inputReader = new BufferedReader(new FileReader("testFile.txt"));

    // code to process the input file

    // Declare a String variable to hold the current line
    String line = null;

    while (inputReader.ready()) {
        // read each line in here
        line = inputReader.readLine();

        // now process the line in some way
        // this will usually be in another method that
        // we pass the line to.
    }

} catch (FileNotFoundException fileNotFound) {
    System.out.println("There was a problem finding the file.");
    fileNotFound.printStackTrace();
} catch (IOException ioException) {
    System.out.println("There was a problem reading the file.");
    ioException.printStackTrace();
} catch (Exception exception) {
    System.out.println("There was a problem.");
    exception.printStackTrace();
} finally {
    try {
        if (inputReader != null) {
            inputReader.close();
        }
    } catch (Exception exception) {
        System.out.println("There was a problem closing the BufferedReader.");
        exception.printStackTrace();
    }
}  

Time for a Lab!

Lab 4 - First I/O, Just the I [Input]


Using Streams - Output

For writing to a file we will need three objects.

FileWriter fileWriter = new FileWriter("output.txt");
BufferedWriter bufferedWriter = new BufferedWriter(fileWriter);
PrintWriter outputWriter = new PrintWriter(bufferedWriter);

You'll never see it that way and we need to get used to nested constructors.

//FileWriter fileWriter = new FileWriter("output.txt");
//BufferedWriter bufferedWriter = new BufferedWriter(fileWriter);
//PrintWriter outputWriter = new PrintWriter(bufferedWriter);

PrintWriter outputWriter = new PrintWriter(new BufferedWriter(new FileWriter("output.txt")));

Here's the full code. Notice that we have two catch blocks, not three as in the reader above.

PrintWriter outputWriter = null;
try {
    outputWriter = new PrintWriter(new BufferedWriter(new FileWriter("output.txt")));

    outputWriter.println("Sample output.");
} catch (IOException inputOutputException) {
    System.out.println("There was a problem writing to the file.");
    inputOutputException.printStackTrace();
} catch (Exception exception) {
    System.out.println("There was a problem.");
    exception.printStackTrace();
} finally {
    try {
        if (outputWriter != null) {
            outputWriter.close();
        }
    } catch (Exception exception) {
        System.out.println("There was a problem closing the PrintWriter.");
        exception.printStackTrace();
    }
}

Another Lab!

Lab 5 – Now the O (Output)