File Access Methods
— print (last updated: Jun 6, 2008) print

Select font size:
In general we can use either a String variable, say filename, or a File variable, say f, to open the initial I/O stream. When working with files, Java I/O starts with an initial FileInputStream object, with minimal functionality, and promotes it to objects of other I/O stream classes. Promoting an object means to use it as the argument for a constructor of a (higher-level) class, usually with more useful levels of functionality. The initial stream object is called the raw stream. This promotion process applies to any InputStream objects, including FileInputStream as well as others such as those created by a socket connection.

Text File Access

  1. Read the contents of the file into the String object contents. The initial FileInputStream object is promoted to an InputStreamReader object in order to use the read member function.
    FileInputStream   istr = new FileInputStream(f); 
    InputStreamReader irdr = new InputStreamReader( istr ); // promote
    
    int size = (int) f.length();  // get the file size (in bytes)
    char[] data = new char[size]; // allocate char array of right size
    irdr.read( data, 0, size );   // read into char array
    irdr.close();
    
    String contents = new String(data);
    
  2. Writing the contents string into a file. The initial FileOutputStream object is promoted to an OutputStreamReader object in order to use the write member function.
    String contents = /* some string */;
    
    FileOutputStream   ostr = new FileOutputStream(f); 
    OutputStreamWriter owtr = new OutputStreamWriter( ostr ); // promote
    
    owtr.write( contents, 0, contents.length() );
    owtr.close();                      // use close to ensure completion
    
  3. Read the contents of a file, line-by-line. Here we use a two-level promotion:
    FileInputStream InputStreamReader BufferedReader.
    in order to use the readLine member function.
    FileInputStream   istr = new FileInputStream(f); 
    InputStreamReader irdr = new InputStreamReader( istr ); // promote
    BufferedReader    brdr = new BufferedReader( irdr );    // promote
    
    String line;
    while ( (line = brdr.readLine()) != null ) 
    {      
      // do something with the line you just read
    }
    brdr.close();
    
  4. Write the contents of a file line-by-line. Again, a two-level promotion:
    FileOutputStream OutputStreamReader PrintWriter.
    in order to use the println member function.
    FileOutputStream   ostr = new FileOutputStream(f); 
    OutputStreamWriter owtr = new OutputStreamWriter( ostr ); // promote
    PrintWriter        pwtr = new PrintWriter( owtr, true );  // promote
     
    /* The "true" in the definition of "pwtr" signifies that each println 
     * transmits the line to the file. If "false", or the boolean argument 
     * is omitted, then println buffers the lines until the print buffer 
     * is filled or the "pwtr.close()" occurs.
     */
    
    while ( /*some condition*/  ) 
    {
      String line = /* some line of text */;
      pwtr.println( line );
    }
    pwtr.close();
    

Binary File Access

Here we are only concerned with reading and writing an an entire binary file in one step, like we did in steps 1 and 2 of the text file access. This is essentially the same operations as we did in these steps; the difference is the choice of stream class used for promotion and the target type.

For programs which require both Read and Write access to a file, the RandomAccess class is the preferred choice.
  1. Read the contents of the file into the byte[] object contents. The initial FileInputStream object is promoted to a BufferedInputStream object in order to use the read member function.
    FileInputStream     istr = new FileInputStream(f); 
    BufferedInputStream bstr = new BufferedInputStream( istr ); // promote
    
    int size = (int) f.length();  // get the file size (in bytes)
    byte[] data = new byte[size]; // allocate byte array of right size
    bstr.read( data, 0, size );   // read into byte array
    bstr.close();
    
  2. Writing the contents array into a file. The initial FileOutputStream object is promoted to a BufferedOutputStream object in order to use the write member function.
    FileOutputStream     ostr = new FileOutputStream(f); 
    BufferedOutputStream bstr = new BufferedOutputStream( ostr );
     
    byte[] contents = /* some binary byte[] array */;
    bstr.write( contents, 0, contents.length );
    bstr.close();
    

Reading and Writing Objects from and to Files

An object can be written to a file as long as it is serializable. This means that the class must implement the Serializable interface. Many standard Java objects are serializable such as GUI Components, data structures classes, standard classes from java.lang, etc.

Classes which are not serializable are typically those which represent some on-going connection, like open files classes (from java.io) and database connection classes (like java.sql.ResultSet). A user-defined class can be made serializable simply by declaring
class MyClass implements Serializable {
  // ...
}
There are no member functions to implement, however, this declaration will only be effective if every object used by this class is itself serializable.

Writing an object to a File:

To write an object to a stream, we promote the initial raw stream obect to an ObjectOutputStream object in order to use the writeOject member function.
FileOutputStream    ostr = new FileOutputStream(f); 
ObjectOutputStream oostr = new ObjectOutputStream( ostr ); 

oostr.writeObject( obj );
oostr.close();  // may be necessary to complete the write

Reading an object from a File

To write an read from a stream, we promote the initial raw stream obect to an ObjectInputStream object in order to use the readOject member function.
FileInputStream    istr = new FileInputStream(f); 
ObjectInputStream oistr = new ObjectInputStream( istr );

Object theObject = oistr.readObject();
oistr.close();  // this is probably not necessary
The type of the object read is usually known; to use it one typically casts it to the known type:
MyClass c = (MyClass) theObject;
Casting to the wrong type will cause an exception to occur, and so if there are more than one possible type for the object, we can usually distinguish between choices using the instanceOf operator in statements like this:
if (theObject instanceOf MyClass)  {
  MyClass c = (MyClass) theObject;
  // etc.
}
Observe that the System.out.println operator is likely to succeed without casting because it uses the member function toString() defined on the Object level.


© Robert M. Kline