Reading and Writing Files


Writing to a file

The steps in writing information to a file are

  1. Open the file, creating an object that writes to the file.
  2. Write all the information that you want to write.
  3. Close the file.
There are several different classes of objects that write to files, but we will only discuss one, PrintWriter. Class PrintWriter is in a package called java.io, so write
  import java.io.*;
to use it.

To open a file, create a PrintWriter object. For example, to open a file called stuff.txt, say

  PrintWriter writer = new PrintWriter("stuff.txt");
The file name does not need to be a fixed string. It can, for example, be a variable whose value is the name of the file to open.

Once you have learned to drive one brand of automobile, you know how to drive others, because the important controls all work the same way. Objects are like that too. Once you know how to use one object of a given class, you know how to use other objects of the same class, because they all have the same methods.

You have already seen how to use System.out.print and System.out.println. There is an object called System.out that can perform methods print and println. Above, we have created another object (referred to by variable writer) that works like System.out. So, for example,

  writer.println("Hello");
writes Hello into the file, stuff.txt, that was opened.

When you have written everything that you want to into the file, close it using

  writer.close();


Formatted printing

There is a convenient method called printf that you can use with System.out or with objects of class PrintWriter that you create. It does a formatted print. You provide it with a format showing what the form of the information should be and then with particular information to be inserted into the format. The format is a string with places, indicated by substrings starting with %, to insert data. For example, %i means to insert an integer. Statement

  int n = 5000;
  writer.printf("There are %d beans in the jar.\n", n)
writes
There are 5000 beans in the jar.
Substring %d asks to insert an integer, given by the next argument, n.

You can have any number of data indicators. The first one refers to the first argument after the format, the second one refers to the second argument after the format, etc. For example,

  int x = 50;
  int y = 471;
  writer.printf("x = %d and y = %d\n", x, y)
prints string
x = 50 and y = 471
on the file that object writer refers to.

You can control how many characters are used to show an integer. Format %5d asks to insert an integer but to add spaces, if necessary, to make a total of 5 characters. You often use that to line things up into columns. For example, the following prints a table of factorials from 1 to 10 using object System.out (assuming that the factorial method is defined in this class).

  int n = 1;
  while(n <= 10)
  {
    System.out.printf("%3d %15d\n", n, factorial(n));
    n++;
  }
Some other format specifiers include %s (a string) and %f (a real number). In fact, you can use %s for any kind of object. The object will implicitly be converted to a string using its toString( ) method.


Reading files

You can create a Scanner object that reads from a file instead of from the keyboard. But to do this, you will need to import both java.io.* and java.util.*. Write

  Scanner reader = new Scanner(new File("data.txt"));
to create a scanner that reads from file data.txt. Use the same Scanner operations as before.

Note. The file name can be any expression of type String. For example, it can be a variable. The value of the expression is the name of the file to open.

Note. Do not forget to say new File. Statement

  Scanner reader = new Scanner("data.txt");
creates a scanner that reads from the string "data.txt", not from the file named data.txt.


Example

Any time you open a file, whether to read from the file or to write to the file, you should take into account the possibility that the file does not exist. Here is a program that reads a file name from the user and shows that file on the screen. Notice that it is careful to recover gracefully if the file does not exist. Statement return; returns from the method immediately. Since there is no answer from a void method, no answer is given.

  import java.util.*;
  import java.io.*;
  
  public class ShowFile
  {
     public static void main(String[] args)
     {
       String filename = null;
       Scanner reader = null;

       try 
       {
	 System.out.print("Which file shall I show? ");
         Scanner keyboard = new Scanner(System.in);
         filename = keyboard.nextLine();
       }
       catch (NoSuchElementException e)
       {
         System.out.println("No file name given");
         return;
       }

       try
       {
         reader = new Scanner(new File(filename));
       }
       catch (FileNotFoundException e)
       {
         System.out.println("Cannot open file " + filename);
         return;
       }

       while(reader.hasNextLine())
       {
         String line = reader.nextLine();
         System.out.println(line);
       }
       reader.close();
     }
  }

More information

File input and output is discussed in Chapter 10.1 and 10.2 of Savitch and Carrano. The additional sections in Chapter 10 cover advanced topics on files.