Java Reference
In-Depth Information
buf.limit(2*charBuf.length()); // Set byte buffer limit
Because each Unicode character occupies 2 bytes, the statement sets the byte buffer limit to twice the
number of characters in
charBuf
.
With the byte buffer set up ready to be written to the channel, you write the data to the file with the state-
ment:
channel.write(buf); // Write buffer to the
channel
You now need to reset the limit and position for both the byte buffer and the view buffer to be ready for
the next proverb to be written. The following two statements do this:
buf.clear();
charBuf.clear();
Calling the
clear()
method for a buffer sets the buffer's position back to 0 and its limit to the capacity.
This example looks a little more complicated than it really is because of all the statements tracing the
states of the buffer. If you delete these, you find the code is quite short.
The output shown for this example was produced on a Microsoft Windows system where a newline is
written as two characters, CR and LF. If you are using Linux or other operating systems that represent a
newline as a single NL character, the values for
position
after the buffer has been loaded by the
For-
matter
object are less.
Direct and Indirect Buffers
When you allocate a byte buffer by calling the static
allocate()
method for the
ByteBuffer
class, you get
an
indirect buffer
. An indirect buffer is not used by the native I/O operations, which have their own buffers.
Data to be written to a file has to be copied from your indirect buffer to the buffer that the native output
routine uses before the write operation can take place. Similarly, after a read operation the data is copied
from the input buffer used by your operating system to the indirect buffer that you allocate.
Of course, with small buffers and limited amounts of data being read, using an indirect buffer doesn't add
much overhead. With large buffers and lots of data, it can make a significant difference, though. In this case,
you can use the
allocateDirect()
method in the
ByteBuffer
class to allocate a
direct buffer
. The JVM
tries to make sure that the native I/O operation makes use of the direct buffer, thus avoiding the overhead of
the data copying process. The allocation and de-allocation of a direct buffer carries its own overhead, which
might outweigh any advantages gained if the buffer size and data volumes are small.
You can test whether a buffer object encapsulates a direct buffer by calling its
isDirect()
method. This
returns
true
if it is a direct buffer and
false
otherwise.
You could try this out by making a small change to the
WriteProverbs
example. Just replace the state-
ment
ByteBuffer buf = ByteBuffer.allocate(2*maxLength + 4);
with the following two statements: