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. For simple programs it is sufficient for each piece of data to be stored one per line.

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 data values until there are no more. "No more" is determined by checking if there is another line of data in the file before trying to read any data. If there is not another line then we say that the "end of file" has been reached and stop trying to read more data.

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 Input 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 Input class to
    // read the name from the keyboard.

    int n = in.nextInt() ;
    System.out.println("Integer was: " + n) ;

    long l = in.nextLong() ;
    System.out.println("Long was: " + l) ;

    double d = in.nextDouble() ;
    System.out.println("Double was: " + d) ;

    float f = in.nextFloat() ;
    System.out.println("float was: " + f) ;

    // Before reading a character the newline left in the input buffer after
    // reading the float is removed by reading the rest of the buffer.
    in.nextLine();
    char c = in.nextChar() ;
    System.out.println("char was: " + c) ;
    in.nextLine();
    // After reading a character the newline character is left in the buffer,
    // so is removed. The next input will then start with the next line in the
    // data file.

    String s = in.nextLine() ;
    System.out.println("String was: " + s) ;

    // Finished with the file, so close it.
    in.close() ;
  }
 }

Note the comments about reading characters of type char. Like reading from the keyboard using class Input data from a file is read into a buffer line-by-line before it is accessed by your program.

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 there is no more data to read. Note the way that the hasNextChar method is used to check if there is another character to read.

// 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.
    while (in.hasNextChar())
    {
      char c = in.nextChar();      
      System.out.print(c);
    }
    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. The next<type> methods read values of the given type, while the hasNext<type> methods determine whether there is a value of the given type available to read, returning true if there is, false otherwise.

If an error occurs 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 Input.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 Input.java this is a toy class, not one to use in a real robust application program.

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.Scanner;

/**
 * An iterator type class to read values from a text file.  This is a subclass of
 * Input that hides the exceptions that can happen when opening a file.  As with
 * Input all errors during use of the iterator result in a message output to the
 * standard error and program termination.
 * This class is useful for people new to Java since it allows them to write programs using
 * input from a file without having to fully understand the read / parse / handle exceptions model
 * of the standard Java classes.  Once exceptions and object chaining are covered this class
 * ought not to be used, it is definitely just an "early stepping stone" utility class for initial
 * learning.
 *
 * @author Russel Winder
 * @version 2005-08-10
 */
public class FileInput extends Input
{
  /**
   * Construct FileInput object given a file name.
   */
  public FileInput(final String fileName)
  {
    //  We really ought to have the line:
    //
    //        super ( new FileInputStream ( fileName ) ) ;
    //
    //  and then the member variable Input.scanner could be private and final as we would want
    //  it to be.  However we must catch all exceptions and FileInputStream can throw
    //  FileNotFoundException and there is no way to put a try block around a statement like
    //  this as it has to be the first statement in the sequence.  So we end up forcing
    //  Input.scanner to be protected and not final just so that we can access it in the
    //  following code.  This code does of course go against all the principle we espouse about
    //  not fiddling with the suprclass variables in the subclass but... This appears to be
    //  something of a misfeature of Java.
    try
    {
      scanner = new Scanner(new FileInputStream(fileName));
    }
    catch (FileNotFoundException fnfe)
    {
      System.err.println("File " + fileName + " could not be found.");
      System.exit(1);
    }
  }

  /**
   * Construct FileInput object given a file name.
   */
  public FileInput(final FileInputStream fileStream)
  {
    super(fileStream);
  }
}

Last updated: September 12, 2008

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


 Search by Google