| Lesson 13 | RandomAccessFile Methods |
| Objective | Use random positioning to read and update file data in place. |
RandomAccessFile lets you jump to any byte offset and read/write primitive
values without rewriting the whole file. It implements both DataInput and
DataOutput, so you can use methods like readInt() or
writeUTF()—but the key value is random positioning.
"r": read‑only"rw": read/write"rws": read/write, synchronous updates to content and metadata"rwd": read/write, synchronous updates to content only| Method | Purpose |
|---|---|
seek(long pos) | Move the file pointer to an absolute byte offset. |
getFilePointer() | Current byte position. |
length() | Total size (bytes). |
setLength(long newLen) | Truncate or extend the file. |
skipBytes(int n) | Advance relatively by n bytes. |
getFD(), getChannel() | Access the underlying FileDescriptor or a NIO FileChannel. |
All DataInput/DataOutput methods | readInt(), writeInt(), readUTF(), writeUTF(), etc. |
This pattern makes random access trivial because each record starts at a predictable offset.
// Each record: [int id][double balance][char[20] name] --> 4 + 8 + 40 = 52 bytes
final int NAME_CHARS = 20;
final int RECORD_SIZE = Integer.BYTES + Double.BYTES + (Character.BYTES * NAME_CHARS);
static long offsetOf(int recordIndex) {
return (long) recordIndex * RECORD_SIZE;
}
static void writeRecord(RandomAccessFile raf, int index, int id, double balance, String name) throws IOException {
raf.seek(offsetOf(index));
raf.writeInt(id);
raf.writeDouble(balance);
// write fixed 20-char name (pad or truncate)
String fixed = String.format("%-" + NAME_CHARS + "s", name);
for (int i = 0; i < NAME_CHARS; i++) {
raf.writeChar(fixed.charAt(i));
}
}
static String readName(RandomAccessFile raf) throws IOException {
StringBuilder sb = new StringBuilder(NAME_CHARS);
for (int i = 0; i < NAME_CHARS; i++) {
sb.append(raf.readChar());
}
return sb.toString().stripTrailing();
}
try (RandomAccessFile raf = new RandomAccessFile("accounts.dat", "rw")) {
// Write two records
writeRecord(raf, 0, 1001, 250.00, "Ada Lovelace");
writeRecord(raf, 1, 1002, 99.99, "Grace Hopper");
// Update balance of record #1 in place
raf.seek(offsetOf(1) + Integer.BYTES); // skip id
raf.writeDouble(149.99); // overwrite balance only
// Read back name from record #0
raf.seek(offsetOf(0) + Integer.BYTES + Double.BYTES);
String name0 = readName(raf);
}
readLine() builds a String using the platform default charset; prefer explicit encodings via NIO if you’re storing text.writeUTF() uses modified UTF‑8; if you need standard UTF‑8, write bytes via NIO.FileChannel + ByteBuffer for bulk I/O.FileChannel/MappedByteBuffer.Ideal for compact binary formats, in‑place updates, and fixed‑record stores. For streaming text or large sequential files, a buffered stream or NIO channel is usually simpler and faster.