UCL Logo

class FileInput
Reading Data from a File

Programs frequently need to read data from files or write data to files. This allows data and information to exist between executions of a program and to be passed between programs. These notes give an introduction to using files, providing a FileInput class for use with the exercises.

Reading data from a file involves the following steps:

1. Decide what type of data is in the file. Many files are treated as text, so you would use Strings when reading the text. However, it is also possible to read other types such as integer or double. The type of data you try to read must match what appears in the file.

2. Determine the file name. Often this is done by asking the user to type in a file name. A file name is any valid Unix or PC file name which may include a relative or absolute path name.

3. Try to open the file. This means that the program will ask for the file to be located and made ready for reading. If the file does not exist or cannot be opened the program may fail, displaying an error message.

4. Once the file is open, data values can be read one by one from the file. Often a loop is used to continually read values until there are no more. "No more" is indicated by the end-of-file or eof condition which is set to true when the end of the file is reached and an attempt is made to read a further data value.

5. When the data has been read from the file, it should be closed. This will disconnect the file from the program and tidy things up.

A class called FileInput is given at the end of these notes. FileInput is similar to the KeyboardInput class but reads data from a file instead of from the keyboard. The following example programs show how it is used to read data from files.

This program reads a number of different types of value from the data file test1.dat:

// Program to test the FileInput class by reading a
// sequence of values of different types.
class FileInputTest1
{
  public static void main(String[] args)
  {
    // Create the FileInput object using the filename
    // test1.dat. Any file name (including a full path name)
    // can be used, or a String variable holding the name
    // can be given.
    FileInput in = new FileInput("test1.dat") ;
    // Could have done this
    // String fname = "test1.dat" ;
    // FileInput in = new FileInput(fname) ;
    // Could have even used the KeyboardInput class to
    // read the name from the keyboard.
    int n = in.readInteger() ;
    System.out.println("Integer was: " + n) ;
    long l = in.readLong() ;
    System.out.println("Long was: " + l) ;
    double d = in.readDouble() ;
    System.out.println("Double was: " + d) ;
    float f = in.readFloat() ;
    System.out.println("float was: " + f) ;
    char c = in.readCharacter() ;
    System.out.println("char was: " + c) ;
    // Note that reading one character leaves the newline
    // and/or carriage return characters still in the input buffer. 
    // On a PC you have to read two extra characters to use them up.
    // On a Unix machine you only need to read one extra character!
    // Watch out for this difference...
    c = in.readCharacter() ;
    c = in.readCharacter() ;
    String s = in.readString() ;
    System.out.println("String was: " + s) ;
    // Finished with the file, so close it.
    in.close() ;
  }
 }

Note the comments about reading characters of type char. Windows/DOS on a PC marks the ends of lines differently from Unix machines, so if you are reading newline or carriage return characters be careful.

The data file test1.dat looks like this:

   123
   12345
   1.2345
   1.23
   c
   This is a string.

The contents of the file are simply ordinary characters. The file can be created by using emacs or jedit to type it in. Each data item (integer, floating point number, text string, etc.) should appear on a separate line, as the newline character is used to mark the end of a data item.

The second example program shows a loop reading input until the eof condition becomes true. Note that in order to work correctly an attempt to read a character has to be made and then followed by a test for eof, before the character can be printed out. If the eof test is not made before printing, the character could be invalid (eof is only set to true once an attempt to read beyond the end of file is made). This accounts for the need to read one character before the loop starts and the order of the statements in the loop body.

// Use a loop to read a sequence of characters.
class FileInputTest2
{
  public static void main(String[] args)
  {
    FileInput in = new FileInput("test1.dat");

    // Note that one character has to be read first
    // before the loop starts.
    char c = in.readCharacter();
    while (!in.eof())
    {
      System.out.print(c);
      c = in.readCharacter();
    }
    in.close();
  }
}

When run, this program simply displays the contents of the data file on the screen, character by character.

The following class provides methods to open and close a file, and read values of type int, long, double, float, char and String. A method eof return true if the end of file has been reached and there are no more values to be read.

If errors occur when trying to open a file or when reading from a file, then an error message will be displayed and your program terminated. So, if your program stops unexpectedly look for an error with the file handling.

Using the class is similar to using KeyboardInput.java. Copy the class below and save it into a file called FileInput.java. Then compile it to get FileInput.class. This .class file should be copied to the directories where you are working on your exercises. Like KeyboardInput.java this is a toy class, not one to use in a real robust application program.

import java.io.*;
/**
 * A simple input class to read values from a file of characters.
 * If any file errors occur, methods in this class will display
 * an error message and terminate the program.
 *
 *@author     Graham Roberts
 *@version    1.2
 */

public class FileInput
{

  /**
   * Instance variables to store file details.
   */
  private String filename = "";
  private BufferedReader reader = null;
  private boolean eof = false;

  /**
   * Construct FileInput object given a file name.
   *
   *@param  fname  Name or pathname of file to open
   */
  public FileInput(String fname)
  {
    filename = fname;
    try
    {
      reader = new BufferedReader(new FileReader(filename));
    }
    catch (FileNotFoundException e)
    {
      error("Can't open file: " + filename);
    }
  }

  /**
   * Close the file when finished
   */
  public void close()
  {
    try
    {
      reader.close();
    }
    catch (IOException e)
    {
      error("Can't close file: " + filename);
    }
  }

  /**
   *Test for end of file.
   *
   *@return    true if end of file has been reached
   */
  public boolean eof()
  {
    return eof;
  }

  /**
   * Read an int value from file.
   *
   *@return    int value read or 0 if read failed.
   */
  public final synchronized int readInteger()
  {
    //
    // The place to hold the data received from the file so
    // that we can parse it to find the int value.
    //
    String input = "";
    int val = 0;

    //
    // Read a String of characters from the file.
    //
    try
    {
      input = reader.readLine();
      if (input == null)
      {
        eof = true;
        return val;
      }
    }
    catch (IOException e)
    {
      error("readInteger failed for file: " + filename);
    }
    //
    // Parse the String to construct an int value.
    //
    try
    {
      val = Integer.parseInt(input);
    }
    catch (NumberFormatException e)
    {
    }
    return val;
  }

  /**
   * Read a long value from file.
   *
   *@return    value of long read or 0L if read failed.
   */
  public final synchronized long readLong()
  {
    //
    // The place to hold the data received from the file so
    // that we can parse it to find the long value.
    //
    String input = "";
    long val = 0L;
    //
    // Read a String of characters from the file.
    //
    try
    {
      input = reader.readLine();
      if (input == null)
      {
        eof = true;
        return val;
      }
    }
    catch (IOException e)
    {
      error("readLong failed for file: " + filename);
    }
    //
    // Parse the String to construct a long value.
    //
    try
    {
      val = Long.parseLong(input);
    }
    catch (NumberFormatException e)
    {
    }
    return val;
  }

  /**
   * Read a double value from file.
   *
   *@return    value of double read or 0.0 if read failed.
   */
  public final synchronized double readDouble()
  {
    //
    // The place to hold the data received from the file so
    // that we can parse it to find the double value.
    //
    String input = "";
    double val = 0.0D;
    //
    // Read a String of characters from the file.
    //
    try
    {
      input = reader.readLine();
      if (input == null)
      {
        eof = true;
        return val;
      }
    }
    catch (IOException e)
    {
      error("readDouble failed for file: " + filename);
    }
    //
    // Parse the String to construct a double value.
    //
    try
    {
      val = (Double.valueOf(input)).doubleValue();
    }
    catch (NumberFormatException e)
    {
    }
    return val;
  }

  /**
   * Read a float value from file.
   *
   *@return    value of float read or 0.0F if read failed.
   */
  public final synchronized float readFloat()
  {
    //
    // The place to hold the data received from the file so
    // that we can parse it to find the float value.
    //
    String input = "";
    float val = 0.0F;
    //
    // Read a String of characters from the file.
    //
    try
    {
      input = reader.readLine();
      if (input == null)
      {
        eof = true;
        return val;
      }
    }
    catch (IOException e)
    {
      error("readFloat failed for file: " + filename);
    }
    //
    // Parse the String to construct a float value.
    //
    try
    {
      val = (Float.valueOf(input)).floatValue();
    }
    catch (NumberFormatException e)
    {
    }
    return val;
  }

  /**
   * Read a char value from file.
   *
   *@return    value of char read or space if read failed.
   */
  public final synchronized char readCharacter()
  {
    //
    // No need to parse anything, just get a character and return
    // it..
    //
    char c = ' ';
    try
    {
      int n = reader.read();
      if (n == -1)
      {
        eof = true;
      }
      else
      {
        c = (char) n;
      }
    }
    catch (IOException e)
    {
      error("readCharacter failed for file: " + filename);
    }
    return c;
  }

  /**
   * Read an String value from file. The String is actually the next
   * complete line of text in the file.
   *
   *@return    String read, empty if read failed.
   */
  public final synchronized String readString()
  {
    //
    // No need to parse anything, just get a string and return
    // it..
    //
    String s = "";
    try
    {
      s = reader.readLine();
      if (s == null)
      {
        eof = true;

        s = "";
      }
    }
    catch (IOException e)
    {
      error("readString failed for file: " + filename);
    }
    return s;
  }

  /**
   * Deal with a file error
   *
   *@param  msg  Error message to display
   */
  private void error(String msg)
  {
    System.out.println(msg);
    System.out.println("Unable to continue executing program.");
    System.exit(0);
  }
}
Last updated: August 30, 2006

Computer Science Department - University College London - Gower Street - London - WC1E 6BT - Telephone: +44 (0)20 7679 7214 - Copyright 1999-2006 UCL


 Search by Google