Is there a way to add data into a RandomAccessFile using seek(long) without writing over the data at that position and beyond? For example:

public static void main(String[] args) throws Exception    {
    RandomAccessFile raf = new RandomAccessFile("test.txt", "rw");
    raf.writeBytes("Hello, World!");
    seek(2);
    raf.writeBytes("Goodbye, World!");
    raf.close();
}

Using that the file would read

HeGoodbye, World!

Is there a way to make it

HeGoodbye, World!llo, World

instead?

The way I was thinking isn't practical enough to use as it involved reading all the data from the desired position to the end and then writing it back into the file after the write("Goodbye, World!"); but in a large file that's not really possible.


So any ideas would be appreciated!

Dani AI

Generated

You cannot "insert" bytes in the middle of a file with RandomAccessFile — the API only overwrites or appends. That means either moving (rewriting) the tail of the file every time, or designing the on-disk layout so inserts never require shifting large ranges. The simple read-and-rewrite tail approach works but is impractical for large files; the other approaches trade extra metadata or background work for fast updates.

Two practical patterns that avoid shifting the entire tail:

  • Append-only log + index (recommended for this task): append every new or updated key/value as a new record and keep an index that maps keys to their latest file offset. On update you write a new record and update the index. Deleted entries are marked with a tombstone; a periodic compaction pass rewrites live entries into a fresh file and rebuilds the index. A compact record layout might look like:
[status:1][keyLen:4][valueLen:4][key bytes][value bytes]
  • Offset-linked records (a variant of what mentioned): store each record with a small header including a nextOffset. To insert, append the new record and perform a tiny overwrite to change the previous record’s nextOffset to point to it. This keeps per-insert IO small, but requires an index or a way to find the previous node quickly and leads to fragmentation that also needs compaction.

If keys/values are mostly bounded in size, fixed-size slots + a free-list is the simplest: compute slot positions, reuse freed slots, and avoid moving data entirely. For heavy-duty performance you can use FileChannel/MappedByteBuffer to copy large ranges in chunks (still copying, but with lower overhead) — see the Java FileChannel docs for available primitives (FileChannel, RandomAccessFile).

For the assignment constraints (must use RandomAccessFile and persist on each HashMap change), the append-only log plus a durable index and occasional compaction gives a clear, crash-tolerant solution without moving the entire file on every update.

Recommended Answers

All 5 Replies

I'm pretty certain you have to read and re-write the data from the insertion point to EOF. How big is the file? There's no problem with (say) 100Mb reading the whole thing into memory, modfying it, the re-writing it.
If your data is more structured than the example the there may be a smarter way to organise it. Eg if consists of records with known formats, and you want to insert a whole record, you can structure the file with each record holding a pointer to the next logical record. Then you can add the new record to the physical end of the file and just overwrite a couple of pointer values to insert it in the right logical position.

Thanks for the reply.
Basically we're required to write every entry in a HashMap, simulating a simple database, to file in order that it is stored. The file size isn't known and should be able to (technically)hold up to Integer.MAX_VALUE entries. But I don't think that the lecturer will expect our implementation to hold that much!

The data is only the HashMap key and a String value. But I was wondering if there was a better way!

Just read & write the HashMap as a single Object using a single read/write call on Object input/output streams. Easy & fast.

Sorry I should have mentioned that I am required to use a RandomAccessFile and to update the file data each time the HashMap is changed ie. adding a new entry or removing an entry from the file. It's just an annoying assignment that has hardly any real-world application.

In that case I would go for the approach outlined in my previous post - chain the records together so you can insert physically at the end but logically in the middle.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.