Buffers
Traditional synchronous I/O is designed for traditional applications. Such applications have the following characteristics:
- Files may be large but not huge. It's possible to read an entire file into memory.
- An application reads from or writes to only a few files or network connections at the same time, ideally using only one stream at a time.
- The application is sequential. It won't be able to do much until it's finished reading or writing a file.
As long as these characteristics hold, stream-based I/O is reasonably quick and operates fairly efficiently. However, if these prerequisites are violated, the standard I/O model begins to show some weaknesses. For example, web servers often need to service hundreds or thousands of connections simultaneously. Scientific, engineering, and multimedia applications often need to manipulate datasets that are gigabytes in size.
Java 1.4 introduced a new model for I/O that is designed more for these sorts of applications and less for the more traditional applications that don't have to do so much I/O. The classes that make up this new I/O library are all found in the java.nio package and its subpackages. The new I/O model does not replace traditional, stream-based I/O. Indeed, several parts of the new I/O API are based on streams. However, the new I/O model is much more efficient for certain types of I/O-bound applications.
Whereas the traditional I/O model is based on streams, the new I/O model is based on buffers and channels. A buffer is like an array (in some implementations it may in fact be an array) that holds the data to be read and written. However, unlike input and output streamseven buffered input and output streamsthe same buffer can be used for both reading and writing. Input channels fill a buffer with data that output channels then drain. Rather than being a part of a channel, a buffer is a neutral meeting ground in which channels exchange data. Furthermore, because buffers are objects accessed via methods, they may not really be arrays. They can be implemented directly on top of memory or the disk for extremely fast, random access. For the right kind of application, the performance gains can be dramatic.
Different buffers have different element types, just as arrays do. For instance, there are byte buffers, int buffers, float buffers, and char buffers. The class library doesn't contain any string buffers or object buffers, but you could write these classes yourself if you found a need. The same basic operations apply to all these different kinds of buffers:
- Allocate the buffer.
- Put values in the buffer.
- Get values from the buffer.
- Flip the buffer.
- Clear the buffer.
- Rewind the buffer.
- Mark the buffer.
- Reset the buffer.
- Slice the buffer.
- Compact the buffer.
- Duplicate the buffer.