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 onlyMethod | 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.