Recommended: Sing it, brah! 5 fabulous songs for developers
JW's Top 5
Optimize with a SATA RAID Storage Solution
Range of capacities as low as $1250 per TB. Ideal if you currently rely on servers/disks/JBODs
Page 3 of 7
| java.nio.Buffer | Abstract base class |
java.nio.ByteBuffer |
Holds bytes. Can be direct or nondirect. Can be read from a ReadableByteChannel. Can be written to a WritableByteChannel.
|
java.nio.MappedByteBuffer |
Holds bytes. Always direct. Contents are a memory-mapped region of a file. |
java.nio.CharBuffer |
Holds chars. Cannot be written to a Channel.
|
java.nio.DoubleBuffer |
Holds doubles. Cannot be written to a Channel.
|
java.nio.FloatBuffer |
Holds floats. Can be direct or nondirect. |
java.nio.IntBuffer |
Holds ints. Can be direct or nondirect. |
java.nio.LongBuffer |
Holds longs. Can be direct or nondirect. |
java.nio.ShortBuffer |
Holds shorts. Can be direct or nondirect. |
You allocate a buffer by calling either allocate(int capacity) or allocateDirect(int capacity) on a concrete subclass. As a special case, you can create a MappedByteBuffer by calling FileChannel.map(int mode, long position, int size).
A direct buffer allocates a contiguous memory block and uses native access methods to read and write its data. When you can arrange
it, a direct buffer is the way to go. Nondirect buffers access their data through Java array accessors. Sometimes you must use a nondirect buffer -- when using any of the
wrap methods (like ByteBuffer.wrap(byte[])) -- to construct a Buffer on top of a Java array, for example.
When you allocate the Buffer, you fix its capacity; you can't resize these containers. Capacity refers to the number of primitive elements the Buffer can contain. Although you can put multibyte data types (short, int, float, long, and so on) into a ByteBuffer, its capacity is still measured in bytes. The ByteBuffer converts larger data types into byte sequences when you put them into the buffer. (See the next section for a discussion
about byte ordering.) Figure 3 shows a brand new ByteBuffer created by the code below. The buffer features a capacity of eight bytes.
ByteBuffer example = ByteBuffer.allocateDirect(8);

Figure 3. A fresh ByteBuffer
The Buffer's position is the index of the next element that will be written or read. As you can see in Figure 3, position starts at zero for a newly allocated Buffer. As you put data into the Buffer, position climbs toward the limit. Figure 4 shows the same buffer after the calls in the next code fragment add some data.
example.put( (byte)0xca ); example.putShort( (short)0xfeba ); example.put( (byte)0xbe );

Figure 4. ByteBuffer after a few puts
Another of the buffer's important attributes is its limit. The limit is the first element that should not be read or written. Attempting to put() past the limit causes a BufferOverflowException. Similarly, attempting to get() past the limit causes a BufferUnderflowException. For a new buffer, the limit equals the capacity. There is a trick to using buffers. Between filling the buffer with data
and writing it on a Channel, the buffer must flip. Flipping a buffer primes it for a new sequence of operations. If you've been putting data into a buffer, flipping it ensures
that it's ready to read the data. More precisely, flipping the buffer sets its limit to the current position and then resets
its position to zero. Its capacity does not change. The following code flips the buffer. Figure 5 depicts the effect of flipping
the sample buffer.