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