The NIO Classes
classes are contained in the packages shown here:
we begin, it is important to emphasize that the NIO subsystem does not replace
the stream-based I/O classes found in java.io,
which are discussed in Chapter 20, and good working knowledge of the stream-based
I/O in java.io is helpful to
system is built on two foundational items: buffers and channels. A buffer holds data. A channel represents an open connection to
an I/O device, such as a file or a socket. In general, to use the NIO system,
you obtain a channel to an I/O device and a buffer to hold data. You then
operate on the buffer, inputting or outputting data as needed. The following
sections examine buffers and channels in more detail.
are defined in the java.nio package.
All buffers are subclasses of the Buffer
class, which defines the core functionality common to all buffers: current
position, limit, and capacity. The current
position is the index within the buffer at which the next read or write
operation will take place. The current position is advanced by most read or
write operations. The limit is the
index value one past the last valid location in the buffer. The capacity is the number of elements that
the buffer can hold. Often the limit equals the capacity of the buffer. Buffer also supports mark and reset. Buffer defines several methods, which
are shown in Table 21-1.
From Buffer, the following specific buffer
classes are derived, which hold the type of data that their names imply:
MappedByteBuffer is a subclass of ByteBuffer and is used to map a file
to a buffer.
the aforementioned buffers provide various get(
) and put( ) methods, which
allow you to get data from a buffer or put data into a buffer. (Of course, if a
buffer is read-only, then put( )
operations are not available.) Table 21-2 shows the get( ) and put( )
methods defined by ByteBuffer. The
other buffer classes have similar methods. All buffer classes also support
methods that perform various buffer operations. For example, you can allocate a
buffer manually using allocate( ).
You can wrap an array inside a buffer using wrap( ). You can create a subsequence of a buffer using slice( ).
are defined in java.nio.channels. A
channel represents an open connection to an I/O source or destination. Channels
implement the Channel interface. It
extends Closeable, and it extends AutoCloseable. By implementing AutoCloseable, channels can be managed
byte get( ) : Returns the byte at the
get(byte vals[ ]), int start, int num) : Copies the invoking buffer into the
array referred to by vals. Returns a
reference to the buffer. If there are not vals.length elements remaining in the
buffer, a BufferUnderflowException is thrown.
get(byte vals[ ], : Copies num elements
from the invoking buffer into the array referred to by vals, beginning at the
index specified by start. Returns a reference to the buffer. If there are not num elements remaining in the
buffer, a BufferUnderflowException is
byte get(int idx) : Returns the byte at
the index specified by idx within the invoking buffer.
ByteBuffer put(byte b) : Copies b into
the invoking buffer at the current position.
Returns a reference to the buffer. If the buffer is full, a
BufferOverflowException is thrown.
ByteBuffer put(byte vals[ ] ) : Copies
all elements of vals into the invoking buffer, beginning at the current
position. Returns a reference to the buffer. If the buffer cannot hold all of
the elements, a BufferOverflowException is thrown.
put(byte vals[ ], int start, int num) : Copies num elements from vals,
beginning at start, into the invoking buffer. Returns a reference to the
buffer. If the buffer cannot hold all of the elements, a
BufferOverflowException is thrown.
put(ByteBuffer bb) : Copies the elements
in bb to the invoking buffer, beginning at the current position. If the buffer
cannot hold all of the elements, a BufferOverflowException is thrown. Returns a
reference to the buffer.
ByteBuffer put(int idx, byte b) : Copies
b into the invoking buffer at the location specified by idx. Returns a
reference to the buffer.
Table 21-2 The get(
) and put( ) Methods Defined for
with a try-with-resources statement. When used
in a try-with-resources block, a
channel is closed automatically when it is no longer needed. (See Chapter 13
for a discussion of try-with-resources.)
to obtain a channel is by calling getChannel(
) on an object that supports channels. For example, getChannel( ) is supported by the following I/O classes:
specific type of channel returned depends upon the type of object getChannel( ) is called on. For
example, when called on a FileInputStream,
RandomAccessFile, getChannel( ) returns a channel of type FileChannel. When called on
a Socket, getChannel( ) returns a SocketChannel.
way to obtain a channel is to use one of the static methods defined by the Files
class. For example, using Files, you
can obtain a byte channel by calling newByteChannel(
). It returns a SeekableByteChannel,
which is an interface implemented by FileChannel.
(The Files class is examined in
detail later in this chapter.)
such as FileChannel and SocketChannel support various read( ) and write( ) methods that enable you to perform I/O operations through
the channel. For example, here are a few of the read( ) and write( )
methods defined for FileChannel.
channels support additional methods that give you access to and control over
the channel. For example, FileChannel
supports methods to get or set the current position, transfer information
between file channels, obtain the current size of the channel, and lock the
channel, among others. FileChannel
provides a static method called open( ), which opens a file and returns
a channel to it. This provides another way to obtain a channel. FileChannel also provides the map( ) method, which lets you map a
file to a buffer.
Charsets and Selectors
other entities used by NIO are charsets and selectors. A charset defines the way that bytes are mapped to characters. You
can encode a sequence of characters into bytes using an encoder. You can decode a sequence of bytes into characters using a
decoder. Charsets, encoders, and
decoders are supported by classes defined in the java.nio.charset package. Because default encoders and decoders are
provided, you will not often need to work explicitly with charsets.
A selector supports key-based,
non-blocking, multiplexed I/O. In other words, selectors enable you to perform
I/O through multiple channels. Selectors are supported by classes defined in
the java.nio.channels package.
Selectors are most applicable to socket-backed channels.
not use charsets or selectors in this chapter, but you might find them useful
in your own applications.