ENGR 131: TEXT FILE INPUT/OUTPUT IN JAVA

Fall 2006, Prof. Branicky


Overview: TextFileIO.java

This document explains how the class TextFileIO can be used to open text files for input/output (aka I/O). The class contains two methods, one for reading from a file (or using it as input) text files and one for writing to a file (or using it as output).

The class is located in the file TextFileIO.java in the ENGR 131 Code Repository. To use its methods in a Java program, it should be copied to the same directory (DrJava and javac/java) or same project (BlueJ) as the program you call its methods from.

Reading from a text file with openRead

The method for opening a file for reading is called openRead. It takes a file name (String) as an input parameter and returns a new Scanner object for reading from that file. Specifically, if you want to open a file for reading, you would include a line like this in your program:

Scanner input = TextFileIO.openRead("infile.txt");

This particular line sets up a Scanner (which we have named input) to read from the file named infile.txt.

Notes:

The Scanner input can now be used to read from this file in the same way that you used a Scanner to read from the keyboard:

Technical Note: You don't have to use "input" as the name of the Scanner. However, the name of the Scanner must match the name that precedes the '.' in the method calls.

Example 1

The following code demonstrates reading from a file by adapting the program "Madlib.java" that took user input from a keyboard. Some lines from the KeyBoard version, commented out with "// KB:", are shown for comparison purposes.
// This file demonstrates reading data from a text file using
// the Scanner class and the TextFileIO.openRead method
//
//  -- M. Branicky, 10/09/06

import java.util.Scanner; // needed for input processing using Scanner

public class ReadDataTrial
{
  public static void main(String args[])
  {
    // Open the file [versus creating a new Scanner for the keyboard]
    Scanner input = TextFileIO.openRead("MadlibDataTrial.txt");
    // KB: Scanner input = new Scanner( System.in );

    // Variables to be used in the story
    double number = 0.0;
    String pluralNoun = "", adjective = "";

    // Get input from file [no need to ask user, else no changes]
    // KB: System.out.print("Enter a plural noun and press : ");
    pluralNoun = input.next();
    // KB: System.out.print("Enter an adjective and press : ");
    adjective = input.next();
    // KB: System.out.print("Enter a number and press : ");
    number = input.nextDouble();

    // Display story [No changes]
    System.out.printf("After the man ate %f %s, he felt very %s.\n",
       number, pluralNoun, adjective);

    // Close the file [NEW]
    input.close();
  }
}
On my computer, the file MadlibDataTrial.txt contains
eggs
full
50
So the program outputs
After the man ate 50.000000 eggs, he felt very full.

Example 2

What if we wanted to process many Madlib's, all stored in one file? On my computer, the file MadlibData.txt contains
eggs full 50
worms icky 3.5
hotdogs sick 11
This file can be processed using a program similar to that above, to produce the output
After the man ate 50.000000 eggs, he felt very full.
After the man ate 3.500000 worms, he felt very icky.
After the man ate 11.000000 hotdogs, he felt very sick.
The program I used to perform this appears below. It is very similar to the foregoing program, except that it uses a while loop to keep processing the file until it reaches the end of the file (and there is nothing more to scan/read). The Scanner class accomplishes this using the hasNext() method, which returns a boolean indicating whether something remains to be read or not.
// This file demonstrates reading data from a text file using
// the Scanner class and the TextFileIO.openRead method
//
//  -- M. Branicky, 10/09/06

import java.util.Scanner; // needed for input processing using Scanner

public class ReadData
{
  public static void main(String args[])
  {
    // Open the file
    Scanner input = TextFileIO.openRead("MadlibData.txt");

    // Variables to be used in the story
    double number = 0.0;
    String pluralNoun = "", adjective = "";

    // Get input from file
    while (input.hasNext()) {
      pluralNoun = input.next();
      adjective = input.next();
      number = input.nextDouble();

      // Display story
      System.out.printf("After the man ate %f %s, he felt very %s.\n",
         number, pluralNoun, adjective);
    }

    // Close the file
    input.close();
  }
}
Technical Note: hasNext() will return false when the only remaining characters in the file are "whitespace" (spaces, tabs, returns, ...).

Writing to a text file with openWrite

The method for opening a file for writing is called openWrite. It takes a file name (String) as an input parameter and returns a new PrintWriter object for writing to that file. Specifically, if you wanted to open a file for writing, you would include a line like this in your program:

PrintWriter output = TextFileIO.openWrite("outfile.txt");

This particular line sets up a PrintWriter (which we have named output) in order to write to the file named outfile.txt.

Notes:

The PrintWriter output can now be used to write to the file in the same way that you used "System.out.*" to write to the screen:

Technical Note: You don't have to use "output" as the name of the PrintWriter. However, the name of the PrintWriter must match the name that precedes the '.' in the method calls.

Example 3

// This file demonstrates writing data to a text file using
// the PrintWriter class and the TextFileIO.openWrite method
//
//  -- M. Branicky, 10/09/06

import java.io.PrintWriter; // needed for output processing using PrintWriter

public class WriteData
{
  public static void main(String args[])
  {
    // Open the file
    PrintWriter output = TextFileIO.openWrite("out.txt");

    // Write output to the file
    output.println("Prints an entire line, plus a carriage return.");
    output.print("Prints a string without ... ");
    output.print("a new line ... ");
    output.println("."); // end the line
    output.println();
    output.println("The square root of 2 is " + Math.sqrt(2.0));
    output.printf("The square root of 2 is %f%n", Math.sqrt(2.0));
    output.printf("%d + %d = %d%n", 2, 2, 2+2);
    output.println(2 + " + " + 2 + " = " + (2+2));
    output.println();

    // Close the file
    output.close();
  }
}

Important Note: If you look closely at the program above, you will see one thing different than we've done before. Namely, in the printf statements, "%n" is used instead of "\n". The reason for this is that Windows uses a different format to end lines in files than MacOSX/Linux/Unix. The "%n" will (tell the Java Virtual Machine to) do the right thing on the different platforms.

The code for TextFileIO.java

This code is provided for completeness. The word "encapsulation" below is nearly synonymous with "hidden". In this case, the details are not as important as being able to use the methods (just like we don't need to know the details of Math.random() to use it appropriately in our programs).

Still, it is not that hard to understand. The major new item is Java's try-catch block to catch exceptions (aka errors) that could be raised, viz. that the file could not be accessed. Briefly, the program tries to execute the code in the try block; if an exception is raised (an error occurs) relating to the file not being found, it is caught by the catch block, which executes some contingency code (in this case, printing an error message and exiting the method and the whole program). To read more about try and catch, see page 645 of Deitel and Deitel.

// This class encapsulates the details of text file IO in Java
// 
// It has two methods:
//    openRead --- takes a filename (String) as a parameter and
//                 returns a Scanner for reading from that file
//    openWrite -- takes a filename (String) as a parameter and
//                 returns a PrintWriter for writing to that file
//
// M. Branicky, 10/09/06

import java.io.File;        // needed for opening/accessing/closing files
import java.util.Scanner;   // needed for input processing using Scanner
import java.io.PrintWriter; // needed for output processing using PrintWriter
import java.io.FileNotFoundException;  // needed for exception handling

public class TextFileIO 
{
  public static Scanner openRead (String filename) {
    Scanner input = null;
    File file = new File(filename);
    try {
      input = new Scanner(file);
    }
    catch (FileNotFoundException f)
    {
      System.out.println(filename + " not found.");
      System.exit(1);
    }
    return input;
  }

  public static PrintWriter openWrite (String filename) {
    PrintWriter output = null;
    File file = new File(filename);
    try {
      output = new PrintWriter(file);
    }
    catch (FileNotFoundException f)
    {
      System.out.println("Could not open "+filename);
      System.exit(1);
    }
    return output;
  }
}

Example Files

All three example programs (plus the two input files above) are also located in the ENGR 131 Code Repository.

Created: 2006-10-09. Last Modified: 2006-10-10.