Java provides the RandomAccessFile class to allow data to be read from and written to at any locations in the file. All of the streams you have used so far are known as read-only or write-only streams. These streams are called sequential streams. A file that is opened using a sequential stream is called a sequential-access file. The contents of a sequential-access file cannot be updated. However, it is often necessary to modify files. Java provides the RandomAccessFile class to allow data to be read from and written to at any locations in a file. A file that is opened using the RandomAccessFile class is known as a random-access file.
The RandomAccessFile class implements the DataInput and DataOutput interfaces, as shown in Figure below. The DataInput interface defines the methods for reading primitive-type values and strings (e.g., readInt, readDouble, readChar, readBoolean, readUTF) and the DataOutput interface defines the methods for writing primitive-type values and strings (e.g., writeInt, writeDouble, writeChar, writeBoolean, writeUTF).
When creating a RandomAccessFile, you can specify one of two modes: r or rw. Mode r means that the stream is read-only, and mode rw indicates that the stream allows both read and write. For example, the following statement creates a new stream, raf, that allows the program to read from and write to the file test.dat:
RandomAccessFile raf = new RandomAccessFile("test.dat", "rw");
If test.dat already exists, raf is created to access it; if test.dat does not exist, a new file named test.dat is created, and raf is created to access the new file. The method raf.length() returns the number of bytes in test.dat at any given time. If you append new data into the file, raf.length() increases.
If the file is not intended to be modified, open it with the r mode. This prevents unintentional modification of the file.
A random-access file consists of a sequence of bytes. A special marker called a file pointer is positioned at one of these bytes. A read or write operation takes place at the location of the file pointer. When a file is opened, the file pointer is set at the beginning of the file. When you read or write data to the file, the file pointer moves forward to the next data item. For example, if you read an int value using readInt(), the JVM reads 4 bytes from the file pointer, and now the file pointer is 4 bytes ahead of the previous location, as shown in Figure below.
For a RandomAccessFile raf, you can use the raf.seek(position) method to move the file pointer to a specified position. raf.seek(0) moves it to the beginning of the file, and raf.seek(raf.length()) moves it to the end of the file. The code below demonstrates RandomAccessFile.
package demo;
import java.io.*;
public class TestRandomAccessFile {
public static void main(String[] args) throws IOException {
try( // Create a random access file
RandomAccessFile inout = new RandomAccessFile("inout.dat", "rw");
) {
// Clear the file to destroy the old contents if exists
inout.setLength(0);
// Write new integers to the file
for(int i = 0; i < 200; i++)
inout.writeInt(i);
// Display the current length of the file
System.out.println("Current file length is " + inout.length());
// Retrieve the first number
inout.seek(0); // Move the file pointer to the beginning
System.out.println("The first number is " + inout.readInt());
// Retrieve the second number
inout.seek(1 * 4); // Move the file pointer to the second number
System.out.println("The second number is " + inout.readInt());
// Retrieve the tenth number
inout.seek(9 * 4); // Move the file pointer to the tenth number
System.out.println("The tenth number is " + inout.readInt());
// Modify the eleventh number
inout.writeInt(555);
// Append a new number
inout.seek(inout.length()); // Move the file pointer to the end
inout.writeInt(999);
// Display the new length
System.out.println("The new length is " + inout.length());
// Retrieve the new eleventh number
inout.seek(10 * 4); // Move the file pointer to the eleventh number
System.out.println("The eleventh number is " + inout.readInt());
}
}
}
Current file length is 800
The first number is 0
The second number is 1
The tenth number is 9
The new length is 804
The eleventh number is 555
A RandomAccessFile is created for the file named inout.dat with mode rw to allow both read and write operations in line 8.
inout.setLength(0) sets the length to 0 in line 11. This, in effect, destroys the old contents of the file.
The for loop writes 200 int values from 0 to 199 into the file in lines 14 and 15. Since each int value takes 4 bytes, the total length of the file returned from inout.length() is now 800 (line 18), as shown in the sample output.
Invoking inout.seek(0) in line 21 sets the file pointer to the beginning of the file. inout.readInt() reads the first value in line 22 and moves the file pointer to the next number. The second number is read in line 26.
inout.seek(9 * 4) (line 29) moves the file pointer to the tenth number. inout.readInt() reads the tenth number and moves the file pointer to the eleventh number in line 30. inout.write(555) writes a new eleventh number at the current position (line 33). The previous eleventh number is destroyed.
inout.seek(inout.length()) moves the file pointer to the end of the file (line 36). inout.writeInt(999) writes a 999 to the file (line 37). Now the length of the file is increased by 4, so inout.length() returns 804 (line 40).
inout.seek(10 * 4) moves the file pointer to the eleventh number in line 43. The new eleventh number, 555, is displayed in line 44.