tags:

views:

245

answers:

2

I've created a java.nio.MappedByteBuffer around a java.io.RandomAccessFile (a file which is only 54 KB in size). The resulting MappedByteBuffer has a "capacity" and "limit" of around 12 KB, so when I try to invoke mybytebuffer.get(i > 13044) or mybytebuffer.put(i > 13044, value) it throws an InvalidIndexException.

All of this behavior is documented in Sun's official javadocs. My question is how I can use java.nio ByteBuffers to read or write anywhere in the file (I need random access). I can't seem to find an example or documentation of Java NIO that illustrates non-sequential access.

A: 

MappedByteBuffers do not themselves offer random access. This is a misunderstanding. Use a SeekableByteChannel for random access.

Jason Knight
+1  A: 

MappedByteBuffer can access files randomly...it is a 'direct byte buffer'. (Specifically, it uses the OS's virtual memory subsystem to map the file to memory.)

You can access bytes randomly as in the code snippet here:

public void doIt() throws FileNotFoundException, IOException {
    File file = new File("myfile");
    RandomAccessFile raf = new RandomAccessFile(file, "rw");
    FileChannel fc = raf.getChannel();      
    MappedByteBuffer mbb = fc.map(MapMode.READ_WRITE, 0, file.length());

    //get a random byte
    byte b1 = mbb.get(SOME_RANDOM_BYTE); 

    //get another random byte
    mbb.position(SOME_OTHER_BYTE_POSITION);
    byte b2 = mbb.get();
}

You can move about the MBB and access bytes (both reading and writing) as you need to.

Stu Thompson
+1. works as long as the file.length() is less than Integer.MAX_INT.
dmeister
I seem to be getting a NonWriteableChannelException using this; I'll look into it.
Jason Knight
If you use a FileInputStream, the channel isn't writeable. If you use a FileOutputStream, the channel isn't readable. Use a RandomAccessFile to produce a channel that is both readable and writeable.
Jason Knight
@Jason Knight: good catch, I have modified my answer. (Learn something new every day!)
Stu Thompson