Java NIO是一种new IO操作API,比原来的IO更高效执行IO操作,比如在磁盘文件读写,TCP/IP网络通讯,内存文件读写等,都是十分高效的。在网上找了一些国人些的资料都是比较简单的例子,都没有比较深入详细介绍其内部机制。没有办法只能自己动手,丰衣足食,看看外国佬写的书<JAVA NIO Programming>。下面几段是比较详细NIO Buffer内部机制:
Buffer Basics
Conceptually, a buffer is an array of primitive data elements wrapped inside an object.The advantage of a Buffer class over a simple array is that it encapsulates data content and information about the data into a single object. The Buffer class and its specialized subclasses define a API for processing data buffers.
NIO Buffer基础
从理论上讲,buffer(缓存数组)就是一个在其内部封装基本数据的数组。buffer比一个简单数组高级就是它封装了数据内容和信息进入一个简单的对象。Buffer类以及他的子类都定义了一组接口来处理数据缓存。
2.1.1 Attributes
There are four attributes all buffers possess that provide information about the contained data elements. These are:
2 1.1属性
所有的buffer都有四个提供关于被其包装数据元素信息的属性。它们是:
Capacity
The maximum number of data elements the buffer can hold. The capacity is set when
the buffer is created and can never be changed.
容量
一个buffer所能持有数据的最大数目。当一个buffer对象被创建时候其容量属性就被创建。而且将不再变化。
Limit
The first element of the buffer that should not be read or written. In other words,the count of live elements in the buffer.
最大限制
buffer的第一个应该被读写的第一个元素。也就是,在buffer内部活对象的数目。
Position
The index of the next element to be read or written. The position is updated
automatically by relative get( ) and put( ) methods.
位置
buffer下一个将被读写的位置索引。位置将相对函数get()和put函数自动更新
Mark
A remembered position. Calling mark( ) sets mark = position. Calling reset( ) sets position = mark. The mark is undefined until set.The following relationship between these four attributes always holds:
0 <= mark <= position <= limit <= capacity
Let's look at some examples of these attributes in action. Figure 2-2 shows a logical view of a newly created ByteBuffer with a capacity of 10.
标记位置
一个被buffer推荐的位置(既默认位置)。调用mark函数使得mak=position.调用reset函数使得position=mak。mark直到被设置之后才有值的。在这些四个属性中保持以下关系:
0 <= mark <= position <= limit <= capacity
让我们实战看看这4个属性的例子吧。图 2-2展示了一个包含10个元素新创建的ByteBuffer 逻辑视图
Figure 2-2.
A newly created ByteBuffer The position is set to 0, and the capacity and limit are set to 10, just past the last byte the buffer can hold. The mark is initially undefined. The capacity is fixed, but the other three attributes can change as the buffer is used.
对于一个新创建的ByteBuffer ,position 被设置为0,capacity 和limit属性被设置为10既最后一个可以缓存的字节。mark 在吃石化时候是没有定义的。容量capacity 都是固定不变的,但是其他四个属性将被改变随着buffer被使用过程中
2.1.2 Buffer API
Let's take a look now at how we can use a buffer. These are the method signatures for
the Buffer class:
Buffer接口
现在让我们看一下我们是如何使用一个buffer对象。一个Buffer 类有一个签名函数:
package java.nio;
public abstract class Buffer {
public final int capacity( )
public final int position( )
public final Buffer position (int newPosition)
public final int limit( )
public final Buffer limit (int newLimit)
public final Buffer mark( )
public final Buffer reset( )
public final Buffer clear( )
public final Buffer flip( )
public final Buffer rewind( )
public final int remaining( )
public final boolean hasRemaining( )
public abstract boolean isReadOnly( );
}
One thing to notice about this API is that methods you would normally expect to return void,
such as clear( ), instead return a Buffer reference. These methods return a reference to
the object they were invoked upon (this). This is a class design technique that allows for
invocation chaining. Chaining invocations allows code like this:
在这些接口中值得我们关注的是那些在通常情况应该没有返回值确返回Buffer对象引用本身的函数,例如clear()函数。这些将返回一个buffer引用给那些调用以上函数的对象使得链式调用时这个类的设计技巧。链式调用代码如下:
buffer.mark( );
buffer.position(5);
buffer.reset( );
to be written like this: 以上调用可以如下链式调用
buffer.mark().position(5).reset( );
The classes in java.nio were designed with invocation chaining in mind. You may have seen invocation chaining used with the StringBuffer class.When used wisely, invocation chaining can produce concise, elegant,and easy-to-read code. When abused, it yields a cryptic tangle of muddled gibberish. Use invocation chaining when it improves readability and makes your intentions clearer. If clarity of purpose suffers when using invocation chaining, don't use it. Always make your code easy for others to read.
java.nio中的此类在设计时考虑到链接调用。你也许看见过链式调用在使用StringBuffer类时候。很明智,链式调用可以生成简介美观而且容易阅读的代码。当链式调用被滥用则产生一种糊涂迷糊的感觉。当提供链式调用使得代码更具有可阅读性,你的目的意图将更清晰。如果在使用链式调用时候没有明确的目的,就不要使用它了。记得总是保持你的代码让别人更容易读懂
Another thing to note about this API is the isReadOnly( ) method. All buffers are readable,but not all are writable. Each concrete buffer class implements isReadOnly( ) to indicate whether it will allow the buffer content to be modified. Some types of buffers may not have their data elements stored in an array. The content of MappedByteBuffer, for example, may actually be a read-only file. You can also explicitly create read-only view buffers to protect the content from accidental modification. Attempting to modify a read-only buffer will cause a ReadOnlyBufferException to be thrown. But we're getting ahead of ourselves.
另外一个值得注意关于这些接口是isReadOnly函数。所有的buffer类都是可读的,但并不是所有都可写。每一个具体的buffer类实现isReadOnly函数来表明其是否允许buffer中的内容被修改。一些类型的buffer病没有保存他们数据元素的数组。例如MappedByteBuffer,其实就是一个只读的文件。你可以明确地创建一个只读视图buffer来保护其内容被意外修改。试图去修改一个只读视图buffer将抛出ReadOnlyBufferException 异常产生。但是目前我们已经超前。