RandomAccessFile in Java

Naveen AnamaneniUpdated · 4 min read
mediumJava 25javafilesio

The RandomAccessFile class in Java, in java.io, lets you read and write at any position in a file, not only from start to end like a stream. It keeps a file pointer, the current position in bytes, which you move with seek(position). This is useful for files made of fixed-size records, where record number n always starts at byte n x recordSize, so it can be read or changed without touching the rest. In this lesson, you will learn its modes and methods and update a record in place.

Constructor and Modes

Declaration
public class RandomAccessFile implements DataOutput, DataInput, Closeable
 
new RandomAccessFile("data.bin", "rw")
ModeMeaning
"r"It is used to open for reading only.
"rw"It opens for reading and writing, creating the file if needed.
"rws" / "rwd"Like "rw", but every write is saved to the disk immediately.

Methods

MethodDescription
seek(long pos)It moves the file pointer to a byte position.
getFilePointer()It returns the current position.
length() / setLength(n)It returns or changes the file size.
readInt(), readDouble(), readUTF()...It reads values at the pointer (like DataInputStream).
writeInt(), writeDouble(), writeUTF()...It writes values at the pointer (like DataOutputStream).
read(byte[]), write(byte[])It reads or writes raw bytes.

Every read or write moves the pointer forward by the number of bytes used.

Example: Fixed-Size Marks Records

Let's see an example that stores each student's marks as one int (4 bytes), then changes the third record without rewriting the file.

Records.java▶ Try it
import java.io.IOException;
import java.io.RandomAccessFile;
 
public class Records {
    static final int SIZE = 4;
 
    public static void main(String[] args) throws IOException {
        try (RandomAccessFile file = new RandomAccessFile("marks.dat", "rw")) {
            int[] marks = {91, 78, 85, 66};
            for (int m : marks) {
                file.writeInt(m);
            }
            System.out.println("Length: " + file.length() + " bytes");
 
            file.seek(2 * SIZE);
            System.out.println("Record 2: " + file.readInt());
 
            file.seek(2 * SIZE);
            file.writeInt(88);
            System.out.println("Pointer after update: "
                + file.getFilePointer());
 
            file.seek(0);
            StringBuilder all = new StringBuilder();
            for (int i = 0; i < file.length() / SIZE; i++) {
                all.append(file.readInt()).append(' ');
            }
            System.out.println("All records: " + all.toString().strip());
        }
    }
}
Output
Length: 16 bytes
Record 2: 85
Pointer after update: 12
All records: 91 78 88 66

Explanation: Four int values make a 16-byte file. Record 2 (counting from 0) starts at byte 8, so seek(8) jumps straight to it. Writing 88 there replaces 85 in place and moves the pointer to byte 12. Finally seek(0) goes back to the start to read everything.

Fixed-Size Records Only

Common Mistakes

Forgetting to seek before reading after a write. The pointer has moved past what you wrote.

Reading past the end. readInt throws EOFException.

Opening with "r" and calling a write method. It throws IOException.

Practice

  1. Easy: Write the numbers 1 to 10 as int values, then read and print only the last three by seeking.
  2. Harder: Store records of a 20-character name (padded) and an int mark, and write a method updateMark(int index, int mark) that changes one record in place.

Quick check: RandomAccessFile

4 questions
1What does seek(12) do?
2Which mode allows both reading and writing?
3Where does record n start if each record is 4 bytes?
4What kind of records suit random access best?

Key Takeaways

Was this tutorial helpful?

Lesson 362 of 482