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.
PrintWriter object (converts a String to a stream of chars)
BufferedWriter object (offers staging area for char stream)
FileWriter object (converts char stream to byte stream)
file receives byte stream from FileWriter object
The corresponding steps in your Java program (in reverse order) are:
String fileName associated with text file.
FileWriter fr = new FileWriter (fileName);
BufferedWriter buffer = new BufferedWriter (fr);
PrintWriter outFile = new PrintWriter (buffer);
outFile.println (data);
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)
{
}
}
}

>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();
}
}
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?
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.