Java Programming   Java Programming
 |Sofia Home | Content Gallery |
Home
Syllabus
Schedule
Lessons
Assignments
Resources

Lesson 13.2 File Streams

Lesson 13.1 showed you how to read and write from input and output streams. In this lesson you'll learn how to use the FileInputStream and FileOutputStream classes to read and write information from disk files.

These two classes read and write to files on your local machine, so they'll only work in applications, not applets. Applets are forbidden to read from or write to files on your local machine.

Before we get into using the file I/O classes, however, we'll take a quick look at the FileDialog class, which allows your users to select the files they wish to process interactively.

The File Dialog Class

The FileDialog class allows you to get a filename from your users by using the built-in facilities of your operating system.

Let's create a GUI application to try out the FileDialog class. We'll call our app FileOpener and base it on MainFrame.java, which you can download from here.

Here are the steps to follow:

Step 1: Basic App
  • Create a new file called FileOpener.java and add the imports for java.awt and java.awt.event.
  • Write the FileOpener class skeleton, extending the MainFrame class.
  • Add two fields: a Button named open, and a TextArea.
  • Add a default constructor. In the constructor:
    1. Set the title to "FileDialog Demo".
    2. Set the layout to BorderLayout
    3. Add the TextArea to the center of your app.
    4. Add the Button to the south. 
    5. Attach your Button to a new Opener object.
    6. End your constructor by calling the show() method.

  • Add an inner class called Opener that implements ActionListener.
  • Add a main() method that creates an instance of FileOpener.

At the end of Step 1, your class should look like this: 

import java.awt.*;
import java.awt.event.*;

public class FileOpener extends MainFrame
{
  Button open = new Button("Open");
  TextArea ta = new TextArea();

  public FileOpener()
  {
    super("FileDialog Demo");

    setLayout(new BorderLayout(5, 5));
    add(open, "South");
    add(ta,   "Center");

    open.addActionListener(new Opener());

    show();
  }

  class Opener implements ActionListener
  {
    public void actionPerformed(ActionEvent ae)
    {
    }
  }

  public static void main(String[] args)
  {
    new FileOpener();
  }
}

Back to Top
Step 2: The FileDialog
The next step is to add the FileDialog. Adding a FileDialog object is easy. Just add your code to the Opener class actionPerformed() method, following these steps:
  • Create a FileDialog variable named fd.
  • Initialize fd using the FileDialog constructor. The constructor requires three arguments:
    1. A Frame object to act as the FileDialog object's parent. Pass MainFrame.this. [Because the code is in the Opener class, this is an Opener object; FileOpener.this is the enclosing FileOpener object]
    2. The title you want to appear on the top of the FileDialog window when it appears. For now, pass "Open".
    3. One of the constants FileDialog.LOAD or FileDialog.SAVE. Since we want to use the standard "File Open" dialog, pass in FileDialog.LOAD.

  • Send the FileDialog object the setFile() message, passing "*.html" as the argument. [We'll look only for HTML files"]
  • Send the FileDialog object the show() message.

The code inside the actionPerformed() method should look like this: 

public void actionPerformed(ActionEvent ae)
{
  FileDialog fd;
  fd = new FileDialog(FileOpener.this, "Open", 
                      FileDialog.LOAD);
  fd.setFile("*.html");
  fd.show();
}

When you run the program and press the "Open" button you will be shown an "Open File" dialog, native to your platform.

Here's what it looks like on my Windows98 box. Note:
  • The dialog buttons say "Open" because we specified the constant FileDialog.LOAD. If we'd used FileDialog.SAVE then the buttons would say "Save".
  • Our title appears at the top of the dialog.
  • The file "mask" we specified [*.html] show in the "File Name" textbox, and only HTML files show in the selection list.

FileOpener application running under Windows 98. Click image to enlarge.

Back to Top
Step 3: Retrieve the Info
When the user closes the FileDialog, you can retrieve the name of the file selected by sending the FileDialog object the getFile() message, and you can retrieve the directory that the file is located in by sending the getDirectory() message.

Both of these return null if the user closes the dialog by pressing the Escape key or by clicking the Cancel button.

Display the directory and file name selected in the TextArea by adding the following code to the bottom of actionPerformed()

String fname = fd.getFile();
String dname = fd.getDirectory();

if (fname == null)
{
  ta.append("File selection cancelled\n");
}
else
{
  ta.append("File = " + dname + fname + "\n");
}

You can download FileOpener.java by clicking on the hyperlink. Here's a screenshot of the program running:

Running the FileDialog Demo program.

The File Stream Classes

Now that you know how to get a file name from the user, you're ready to work with the two stream classes: FileInputStream and FileOutputStream.

To use either of these classes you will have to perform these three steps:

  1. Open a file using a constructor.
  2. Read or write to the file.
  3. Close the file when you're done.

Opening a FileStream

To open a FileInputStream, first create a FileInputStream variable, and set it to null like this:
 
FileInputStream fis = null;

Next, construct your stream in a try-catch block like this. [Assuming fname holds the name of the file you're trying to open.] 

try 

  fis = new FileInputStream(fname);
  // Read and write here
}
catch(FileNotFoundException e) 
{
  ta.append("Couldn't open file");
}
Back to Top

Reading the File

Once you've opened your file, you can read it a byte at a time, just like you did with System.in. Because the FileInputStream read() method can throw IOException, you'll have to catch that as well as FileNotFoundException.

The following loop reads the entire file selected and appends it to a TextArea named ta. The changes from the previous code snippet are highlighted.
try 

  fis = new FileInputStream(fname);

  String text = "";
  int ch;
  while ((ch = fis.read()) != -1)
    text += (char) ch;

  ta.setText(text);
  ta.setCaretPosition(0);
}
catch(FileNotFoundException e) 
{
  ta.append("Error opening file\n"); 
}
catch (IOException ie)
{
  ta.append("Error reading file\n");
}

Closing the File

The last step is to close the file. Do this by calling the close() method in a finally block after the last catch block.

It is possible that closing the file will also throw an IOException as well. If the disk is full, for instance, this could occur. Because of that, you have to put the call to close() in its own try-catch block.

Your code should look like this:

finally
{
  try
  {
    if (fis != null) fis.close();
  }
  catch (IOException ioe) { }
}

The FileRead application follows each of these steps and modifies the FileOpener program so that it reads the file selected by the user. You can download the program and run it on your own machine or simply look at this screen shot of it running on mine:

Running the FileInputStream Demo program.
Back to Top

The Need for Speed

Rather than reading a byte at a time, you can also read and write a whole byte array at once. This can be much faster.

To do this, simply create a byte array like this:

byte[ ] buf = new byte[ fis.available()];

The InputStream available() method tells you how many characters are waiting to be read, and can be used to size your array. Of course, you have to make sure the file is open first.

Once you've created your array, you simply pass the variable buf to read() or write(), and eliminate the entire loop.

Something to Talk About

Can you answer this? Look through FileOpener.java. What lines would have to be changed to:
  1. Display only Java source code files in the selection list.
  2. Display as Save As dialog box with the title "Save Source Code As...".

Please continue to the next section of this lesson.

 

Back to Top

 

Content Developed by Stephen Gilbert, Licensed under a Creative Commons License
Published by the Sofia Open Content Initiative
© 2004 Foothill-De Anza Community College District &The William and Flora Hewlett Foundation