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) { }
}
}