CSC 012

Introduction to Computer Science

 

Summary of 5/6 Lecture

Output Files

The last time we met, we described the process of converting input files from streams of bytes to appropriate data types.  Today we'll see how to reverse the process and send output to a file, rather than to the screen.

  1. PrintWriter object (converts a String to a stream of chars)

  2. BufferedWriter object (offers staging area for char stream)

  3. FileWriter object (converts char stream to byte stream)

  4. file receives byte stream from FileWriter object

The corresponding steps in your Java program (in reverse order) are:

  1. String fileName associated with text file.

  2. FileWriter fr = new FileWriter (fileName);

  3. BufferedWriter buffer = new BufferedWriter (fr);

  4. PrintWriter outFile = new PrintWriter (buffer);

  5. outFile.println (data);

  6. outFile.close();

Our first example mimicked the familiar "Hello World" program, sending output to a file rather than to the screen.

//File:    Hello0.java
import java.io.*;
import CSLib.*;

class Hello0
{
    public static void main (String [] args)
    {
        InputBox in = new InputBox();
        in.setPrompt ("What's the name of your file? ");
        String fileName = in.readString();
       
        //FileWriters convert char streams to byte streams
        FileWriter fw = new FileWriter (fileName);
       
        //PrintWriters convert Strings to char streams                
        PrintWriter outFile = new PrintWriter (fw);
       
        outFile.println ("Hi there gang!!. Ain't this great?");
        outFile.close();
    }
}

An attempt at compiling this program generated the following error message:

Hello0.java:14: unreported exception java.io.IOException; must be caught or declared to be thrown
FileWriter fw = new FileWriter (fileName);
^
1 error

As we learned last time, the creation of I/O objects can generate I/O exceptions.  Java requires that we check for these exceptions.  So the following modified version works just fine:

//File:    Hello.java
import java.io.*;
import CSLib.*;

class Hello
{
    public static void main (String [] args)
    {
        InputBox in = new InputBox();
        in.setPrompt ("What's the name of your file? ");
        String fileName = in.readString();
       
        try
        {
            //FileWriters convert char streams to byte streams
            FileWriter fw = new FileWriter (fileName); //throws IOException
           
            //PrintWriters convert Strings to char streams                
            PrintWriter outFile = new PrintWriter (fw);
           
            outFile.println ("Hi there gang!!. Ain't this great?");
            outFile.close();     //NOTE: It's important to close output files
                                      //     after completing output.
                                      //     Otherwise, you can lose some or all
                                      //     of your data.
        }
        catch (IOException e)
        {
        }
    }
}

wpe12E.jpg (5013 bytes)

>type test.txt
Hi there gang!!. Ain't this great?

This is probably a good time to mention an alternative to the try-catch clause.  Checking for exceptions is much like a game of hot potato.  If you don't provide for the I/O exceptions, then you can throw it to the calling program.  The following is an acceptable rewrite of the previous Hello program.

//File:    Hello2.java
import java.io.*;
import CSLib.*;

class Hello2
{
    public static void main (String [] args) throws IOException
    {
        InputBox in = new InputBox();
        in.setPrompt ("What's the name of your file? ");
        String fileName = in.readString();
       
        //FileWriters convert char streams to byte streams
        FileWriter fw = new FileWriter (fileName); //throws IOException

        //PrintWriters convert Strings to char streams                
        PrintWriter outFile = new PrintWriter (fw);
           
        outFile.println ("Hi there gang!!. Ain't this great?");
        outFile.close();    //NOTE: It's important to close output files
                                    //     after completing output.
                                    //     Otherwise, you can lose some or all
                                    //     of your data.
    }
}

Finally, output to a file can be buffered.  That is, rather than sending data items one by one to the file (which is time consuming), we can collect data in RAM ( in an area called a buffer) and occasionally send data to the file.  This is accomplished through the BufferedWriter class as follows:

//File:    BufferedHello.java
import java.io.*;
import CSLib.*;

class BufferedHello
{
    public static void main (String [] args) throws IOException
    {
        InputBox in = new InputBox();
        in.setPrompt ("What's the name of your file? ");
        String fileName = in.readString();
       
        //FileWriters convert char streams to byte streams
        FileWriter fr = new FileWriter (fileName);
       
        BufferedWriter buffer = new BufferedWriter (fr);
       
        //PrintWriters convert Strings to char streams
        PrintWriter outFile = new PrintWriter (buffer);
       
        outFile.println ("Hi there gang!!. Ain't this great?");
        outFile.close();
    }
}

Command Line Arguments

At long last, we can answer the question:

In the line    public static void main (String [] args)    whats the String [] args for?

The answer is that the parameter "String [] args" provides a way to communicate information to the program from the command line.  Let's look at the following example:

//File:    TestArgs.java
public class TestArgs
{   
    public static void main (String [] args)
    {
        System.out.println ("args [0] = " + args [0]);
        System.out.println ("args [1] = " + args [1]);
        System.out.println ("args [2] = " + args [2]);
    }
}

>java TestArgs How are you?
args [0] = How
args [1] = are
args [2] = you?

Clearly, String [] args represents an array of Strings. By adding a sequence of Strings to the command line, as we just did, the array is filled with those Strings.  In fact, this provides an interesting way for the user to inform the program about files.

//File:    HelloArgs.java
import java.io.*;

class HelloArgs
{
    public static void main (String [] args) throws IOException
    {
//        Don't need to ask the user for file name.    
//        System.out.print ("What's the name of your file? ");
//        String fileName = Keyboard.readString();
       
        //FileWriters convert char streams to byte streams
        FileWriter fr = new FileWriter (args[0]);
        //Pass the filename through the command line argument
       
        //PrintWriters convert Strings to char streams
        PrintWriter outFile = new PrintWriter (fr);
       
        outFile.println ("Hi there gang!!. Ain't this great?");
        outFile.close();
    }
}

>java HelloArgs output.txt

>type output.txt
Hi there gang!!. Ain't this great?

File Output of Tables

It's one thing to output a String to a file, but how about something a bit more complicated.  The following code has been added to our NumberList class:

    //The following function outputs a list of n ints, one number per line,
    //to fileName

    public static void writeIntList (String fileName, int [] list, int n)
    {
           try
            {
                FileWriter fr = new FileWriter (fileName);
                BufferedWriter buffer = new BufferedWriter (fr);
                PrintWriter outFile = new PrintWriter (buffer);

               for (int row=0; row<n; row++)
                {
                    outFile.println (list[row]);
                }
           
                outFile.close();
            }
           catch (IOException e)
            {
            }
    }

Finally, the following function outputs a table of ints.

    //The following function outputs a table of ints containing r rows and c columns
    //to fileName

    public static void writeTable (String fileName, int [] [] list, int r, int c)
    {
           try
            {
                FileWriter fr = new FileWriter (fileName);
                BufferedWriter buffer = new BufferedWriter (fr);
                PrintWriter outFile = new PrintWriter (buffer);

                for (int row=0; row<r; row++)
                {
                   for (int col=0; col<c; col++)
                    {
                        outFile.print (list [row] [col] + "\t");
                    }
                    outFile.println();
                }
           
                outFile.close();
            }
           catch (IOException e)
            {
            }
    }

Putting it all together, a driver for this function might look as follows:

//File:    TestTableArgs.java
public class TestTableArgs
{   
    public static void main (String [] args)
    {
           int [] [] table = new int [8][5];

            String inFile = args[0];
            int [] results = NumberList.readTable (inFile, table);
       
           int rows = results [0];
            int cols = results [1];
       
            String outFile = args[1];
            NumberList.writeOutTable (outFile, table, rows, cols);
        }
}


Lab Exercise.  Write a program that reads a list of integers from the data file infile, calculates the average, and then outputs the list and the average to an output file.  The output file should look as follows:

95
83
56
100
75
86
81
68
92
83

The average is: 81

Take a look at my solution after you complete your own attempt.


Back to CSC 012 Home Page