RandomAccessFile class

 

                  See DataInput  and DataOutput  for descriptions of RandomAccessFile's inherited methods.

 

 

RandomAccessFile has these input methods

because it implements DataInput:

 

It also has these output methods

because it implements DataOutput:

 

.readBoolean( )                     Reads one byte and returns true or false if it was

                                                zero or non-zero.

.readByte( )                            Reads and returns a byte.

.readChar( )                           Reads and returns a char.

.readDouble( )                       Reads eight bytes and returns a double.

.readFloat( )                           Reads four bytes and returns a float.

.readFully( byte[ ] )               Reads bytes into an array.

.readFully( byte[ ], offset, len)     Reads len bytes into an arry starting at offset.

.readInt( )                               Reads four bytes and returns an int.

.readLine( )                            Reads the next line of text from the input stream.

.readLong( )                          Reads eight bytes and returns a long.

.readShort( )                          Reads two bytes and returns a short.

.readUnsignedByte( )           Reads a byte, extends to int, returns the range 0 -255.

.readUnsignedShort( )         Reads two bytes and returns int in range 0 to 65535.

.readUTF( )                             Reads in a String encoded in modified UTF-8.

.skipBytes( num )                 Skips num bytes of the input stream.

 

plus these below

 

.read( )                          to read a byte

.read( byte[ ] )                 to read up to  b.length bytes into a byte array

.read ( byte[ ], offset, len)  read up to len bytes into a byte array at offset.

.getFilePointer ( )

.length

.seek(...)

.setLength(...)                      below - see table

 

write( int ) - Writes the eight low-order bits of an int.

write( byte[ ] ) - Writes all the bytes in a byte array.

write( byte[ ], offset, len ) - Writes len  from a byte array starting at offset.

writeBoolean( boolean ) - Writes a one-byte boolean value.

writeByte( int ) - Acts the same as write( int b ) above

writeBytes( String ) - Writes low order bytes of all the chars in a String.

writeChar( int ) - Writes a two-byte char value from the low end of an int.

writeChars( String ) - Writes two char bytes of all the chars in a String.

writeDouble( double ) - Writes an eight-byte double value.

writeFloat( float ) - Writes a four-byte float value.

writeInt( int ) - Writes a four-byte int value.

writeLong( long ) - Writes an eight-byte long value.

writeShort( int ) - Writes two byte short value from low end of an int.

writeUTF( String ) - Writes a String in special modified UTF format

 

  RandomAccessFile implements the methods from the DataOutput and DataInput interfaces. Most interestingly, it provides a movable pointer into the file.  You can use the pointer to control where the next read or write operation will occur.

 

  You must supply a second parameter to all RandomAccessFile constructors when you provide the usual File object or String filepathname. The second parameter must be either "r" (for read) or "rw" (for read-write).  Always enclosed in double quotes.  i.e.

 

File f = new File(" yourfilenamepath ");

RandomAccessFile raf = new RandomAccessFile( f, "r" );

or

RandomAccessFile raf = new RandomAccessFile( "yourfilenamepath", "r" );

 

  Specifying "rw" for a non-existant file will create it.

 

  Writing off the end of files simply extends their size.

 

   RandomAccessFile has no buffering to improve performance.

 

  You cannot use RandomAccessFile  to read or write objects.

 

  To RandomAccessFile, a file appears as large array of bytes, with a byte pointer in it.  The pointer, which starts at zero, is a byte index to the current read/write point in the file. 

 

  You cannot use the RandomAccessFile pointer as a record pointer.  You must keep track of the file's contents on a byte-by-byte basis. It doesn't provide a record-by-record basis.The next read or write operation occurs at the pointer.

 

If you read a byte (as with readByte( )) the pointer moves up one byte. 

If you read a 16-bit char (as with readChar( )) the pointer moves up two bytes. 

If you write a byte to the end of the file (as with writeByte( int b )) you add one byte to the length of the file.

If you write a char to the end of the file (as with writeChar( int c )) you add two bytes to the length of the file.

 

  You can move the pointer yourself, without doing any reads or writes.  RandomAccessFile supplies several methods for manipulating the pointer or the length of the file.

 

Pointer:

Use Method:

To obtain the pointer's current offset into the file

getFilePointer( )   -  returns a long -

To move the pointer to a desired position in the file

seek( n )

To skip over n bytes, also updating the pointer

skipBytes( n )  - a DataInput method -

 

 

Length of File:

Use Method:

To find the length of the file in bytes  ( includes +2  for endings)

length( )   -  returns a long -

To truncate the file

setLength(...)   <  file length

To extend the file  (zero-filled)

setLength(...)   >  file length

 

  RandomAccessFile implements the input methods from the DataInput interface plus the corresponding output methods from the DataOutput interface. 

 

  The read methods above announce end-of-file by throwing an EOFException.  This occurs if the span of a read operation extends beyond the end of the file.  Other typical problems encountered during reading still throw a regular IOException.

 

  There are three exceptions to the above situation.  They are in three extra read(...) methods provided by  RandomAccessFile which are not part of the DataInput interface. These three methods do not throw an EOFException at end-of-file.  Instead they return a -1.  They are:

 

read( ) to read a byte

read( byte[ ] ) to read up to  b.length bytes into a byte array

read ( byte[ ], offset, len)  to read up to len bytes into a byte array starting at offset.

 

  RandomAccessFile's three extra read(...) methods correspond exactly to these three methods from the DataInput interface, except for not throwing the EOFException.

 

This RandomAccessFile method

otherwise corresponds to

this DataInput method

read( )

readByte( )

read( byte[ ] b)

readFully( byte[ ] b)

read ( byte[ ] b, int off, int len) 

readFully( byte[ ] b, int off, int len) 

 

  You cannot extend the length of a file by writing into the middle of it. Writing after repositioning the pointer inside a file just overwrites the affected bytes, starting at the pointer position. 

 

  You can only extend the size of a file by one of the following four means:

 

(1) writing which starts prior to the end of the file but goes beyond the end

(2) writing which starts at the end and goes beyond it

(3) writing which starts beyond the end because you set the pointer beyond the end before doing the writing.  (In which case the intervening bytes, from the old end up to the start of the writing, will be made zeroes.)

(4) without writing, specifying a length greater than the present length using setLength(...).  In this case the extension created will be all zeroes.

 

  You can use RandomAccessFile to append to files.  The snippet below adds a String to the end of a byte text file by first setting the pointer to the end of the file. Here, because we are writing to a byte file, the writeBytes(...) method is used.  It puts out only the low-end byte of each String character.

 

import java.io.*;

 

try {

    RandomAccessFile raf = new RandomAccessFile("c:\\test.txt", "rw");

    raf.seek( raf.length( ) );                            // sets pointer to end

    raf.writeBytes( "aStringAtTheEnd" );     // write the low order bytes of these chars

    raf.close();

} catch (Exception ex) { }

 

  You can use RandomAccessFile to read files sequentially.  This snippet reads and prints a byte text file.  Each byte is cast to a char for printing.

 

import java.io.*;

 

try { RandomAccessFile raf = new RandomAccessFile(" yourfile ", " r ");

        while ( raf.getFilePointer( ) < raf.length( ) ) {

            byte b = raf.readByte( );

            char c = ( char ) b;

            System.out.print( c );

        }

        raf.close( );

    } catch (Exception e) { }

}

 

  You can use RandomAccessFile to perform direct access on records in a fixed-length file.  This example solicits a record number from the console and uses it to index into a fixed-length byte file, displaying the appropriate record back onto the console. 

 

(Note there cannot be any end-of-line characters between the records in the file, or the byte counts would be thrown off.  If there were end-of-line characters present in the file, the record length would have to accommodate them.)

 

import java.io.*;

import java.text.*;

import java.util.*;

public class DirectByteAccess {

    public static void main(String[ ] args) {

        InputStreamReader isr = new InputStreamReader( System.in );

        BufferedReader br = new BufferedReader( isr );

        int maxrcds = 100;                                                // define file size - 100 records here

        int rcdlength = 80;                                                // define record lengths - 80 bytes here

        int x;

        while ( true ) {

            System.out.println( " \nEnter desired record number:" );

            try {

                String s = br.readLine( );                             // get desired record number from console

                if ( s.equals("") ) {                                         // check for just Enter key being hit

                    s = "0";

                }      

                try {

                   x = Integer.parseInt( s );                           // check for a valid integer in request

                }

                catch (NumberFormatException e) { x = 0; }                                                                            

                if ( x == 0 | x > maxrcds ) {                            // check for request out of file range

                    System.out.println( "Invalid record number. Try Again." );

                    continue;

                } else {

                    RandomAccessFile raf = new RandomAccessFile( "yourfile", "r" );                                 

                    byte[ ] b = new byte[ rcdlength ];           // set length of read operation

                    raf.seek( (x - 1) * rcdlength );                  // set pointer to correct record

                    raf.read( b );                                              // read into array b[ ]

                    System.out.println( "Record  " + x + ": " );

                    for ( int y = 0;  y < rcdlength;  y++ ) {      // print record's bytes from array

                        System.out.print( (char)  b[ y ] );

                    }

                    continue;

                }

            } catch (IOException e) {  }

        }

    }

}

 

 The next snippet shows the changes to the above example (starting at the raf creation statement) if you were to use a file consisting of (16 bit) Unicode characters instead of (8 bit) bytes.  This affects both record length calculations and method selection.  Commented lines show the changes.

 

                    RandomAccessFile raf = new RandomAccessFile( "yourfile", "r" ); 

                    char[ ] c = new char[ rcdlength ];           // now uses an array of chars, not bytes

                    raf.seek( (x - 1) * rcdlength * 2);              // note the doubling of the pointer calculation

                    System.out.println("Record  " + x + ": ");

                    for ( int y = 0; y < rcdlength; y++ ) {                       

                        System.out.print( raf.readChar( ) );   // now reads chars and prints them

                   }

 

 Below is a program using RandomAccessFile to write a test file for the above example.  The file consists of 15 Unicode records of 80 1's through 80 F's.

 

import java.io.*;

public class WriteUTFFile {

    public static void main(String[ ] args) {

        char[ ] rec = new char[ 80 ];

        try {

            RandomAccessFile raf = new RandomAccessFile( "yourfile", "rw" ); 

            char[ ] F = { '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };

            for ( int y = 0;  y < 15;  y++) {

                for ( int x = 0;  x < 80;  x++) {

                    rec[ x ] = F[ y ];

                }

                String s = new String( rec );

                raf.writeChars( s );

            }

        } catch (IOException e) { }

    }

}