继续前文------->>>>>>>>>>>>>
压缩:因为不是常用的函数,所以
| compact() Compacts this buffer (optional operation). |
标记:缓冲区四种属性中的三种。第四种,标记,使缓冲区能够记住一个位置并在之后将其返回。缓冲区的标记在mark( ) 函数被调用之前是未定义的,调用时标记被设为当前位置的值。
public final Buffer mark()
- Sets this buffer's mark at its position.
reset
public final Buffer reset()
-
Resets this buffer's position to the previously-marked position.
Invoking this method neither changes nor discards the mark's value.
-
-
Returns:
- This buffer Throws:
-
InvalidMarkException
- If the mark has not been set
注意不要混淆 reset( )和clear( )。clear( )函数将清空缓冲区,而 reset( )位置返回到一个先前设定的标记。
举例:buffer.position(2).mark().position(4); 结果为------>>>>
如果这个缓冲区现在被传递给一个通道,两个字节(“ow”)将会被发送,而位置会前进到6 。如果我们此时调用 reset( ),位置将会被设为标记,如下图 所示。再次将缓冲区传递给通道将导致四个字节(“llow”)被发送。
比较:所有的Buffer子类都实现了Comparable接口,并重写了Object类中的equals方法。有时候比较两个缓冲区所包含的数据是很有必要的。所有的缓冲区都提供了一个常规的equals( )函数用以测试两个缓冲区的是否相等,以及一个 compareTo( )函数用以比较缓冲区。
compareTo(ByteBuffer that) Compares this buffer to another. |
equals(Object ob) Tells whether or not this buffer is equal to another object. |
public abstract class ByteBuffer
extends Buffer implements Comparable
{
// This is a partial API listing
public boolean equals (Object ob)
public int compareTo (Object ob)
}
两个缓冲区可用下面的代码来测试是否相等:
if (buffer1.equals (buffer2)) {
doSomething( );
}
两个缓冲区被认为相等的充要条件是:
两个对象类型相同。包含不同数据类型的 buffer 永远不会相等,而且 buffer绝不会等于非 buffer 对象。
两个对象都剩余同样数量的元素。Buffer 的容量不需要相同,而且缓冲区中剩余数据的索引也不必相同。但每个缓冲区中剩余元素的数目(从位置到上界)必须相同。
在每个缓冲区中应被 Get ()函数返回的剩余数据元素序列必须一致。 如果不满足以上任意条件,就会返回 false 。
两个属性不同的缓冲区也可以相等。
缓冲区也支持用compareTo( ) 函数(比较缓冲区的大小,与equals方法不同)以词典顺序进行比较。这一函数在缓冲区参数小于,等于,或者大于引用compareTo() 的对象实例时,分别返回一个负整数,0 和正整数。这些就是所有典型的缓冲区所实现的java.lang.Comparable 接口语义。这意味着缓冲区数组可以通过调用 java.util.Arrays.sort() 函数按照它们的内容进行排序。 与equals()相似,compareTo( )不允许不同对象间进行比较。但 compareTo()更为严格:如果您传递一个类型错误的对象,它会抛出ClassCastException 异常,但 equals()只会返回false 。
比较是针对每个缓冲区内剩余数据进行的,与它们在 equals()中的方式相同,直到不相等的元素被发现或者到达缓冲区的上界。如果一个缓冲区在不相等元素发现前已经被耗尽,较短的缓冲区被认为是小于较长的缓冲区。不像 equals(),compareTo()不可交换:顺序问题。在本例中,一个小于零的结果表明 buffer2小于 buffer1,而表达式的值就会是 true:
if (buffer1.compareTo (buffer2) < 0) {
doSomething( );
}
批量移动:缓冲区的涉及目的就是为了能够高效传输数据。一次移动一个数据元素,那样并不高效。buffer API 提供了向缓冲区内外批量移动数据元素的函数。
public abstract class CharBuffer
extends Buffer imp lements CharSequence, Comparable
{
// This is a partial API listing
public CharBuffer get (char [] dst)
public CharBuffer get (char [] dst, int offset, int length)
public final CharBuffer put (char[] src)
public CharBuffer put (char [] src, int offset, int length)
public CharBuffer put (CharBuffer src)
public final CharBuffer put (String src)
public CharBuffer put (String src, int start, int end)
}
有两种形式的get( ) 可供从缓冲区到数组进行的数据复制使用。第一种形式只将一个数组作为参数,将一个缓冲区释放到给定的数组。第二种形式使用 offset 和length 参数来指定目标数组的子区间。这些批量移动的合成效果与前文所讨论的循环是相同的,
但是这些方法可能高效得多,因为这种缓冲区实现能够利用本地代码或其他的优化来移动数据。
对 get( )的这一引用:
buffer.get(myArray);
等价于:
buffer.get(myArray,0,myArray.length);
如果您想将一个小型缓冲区传入一个大型数组,您需要明确地指定缓冲区中剩余的数据长度。上面的第一个例子不会如您第一眼所推出的结论那样,将缓冲区内剩余的数据
元素复制到数组的底部。要将一个缓冲区释放到一个大数组中,要这样做:
char [] bigArray = new char [1000];
// Get count of chars remaining in the buffer
int length = buffer.remaining();
// Buffer is known to contain < 1,000 chars
buffer.get (bigArrray, 0, length);
// Do something useful with the data
processData (bigArray, length);
public CharBuffer get(char[] dst, int offset, int length)
-
Relative bulk
get method.
This method transfers characters from this buffer into the given destination array. If there are fewer characters remaining in the buffer than are required to satisfy the request, that is, iflength > remaining(), then no characters are transferred and a
BufferUnderflowException
is thrown.Otherwise, this method copies length characters from this buffer into the given array, starting at the current position of this buffer and at the given offset in the array. The position of this buffer is then incremented bylength.
In other words, an invocation of this method of the form src.get(dst, off, len) has exactly the same effect as the loop
for (int i = off; i < off + len; i++) dst[i] = src.get();
except that it first checks that there are sufficient characters in this buffer and it is potentially much more efficient.
char [] smallArray = new char [10];
while (buffer.hasRemaining()) {
int length = Math.min (buffer.remaining(), smallArray.length);
buffer.get (smallArray, 0, length);
processData (smallArray, length);
}
put() 的批量版本工作方式相似,但以相反的方向移动数据, 从数组移动到缓冲区。他们在传送数据的大小方面有着相同的语义:
buffer.put(myArray);
等价于:
buffer.put(myArray,0,myArray.length);
如果缓冲区有足够的空间接受数组中的数据(
buffer.remaining()>myArray.length),数据将会被复制到从当前位置开始的缓冲区,并且缓冲区位置会被提前所增加数据元素的数量。如果缓冲区中没有足够的空间,那么不会有数据被传递,同时抛出一个 BufferOverflowException 异常。
也可以通过调用带有一个缓冲区引用作为参数的 put() 来在两个缓冲区内进行批量传递。
buffer.put(srcBuffer);
这等价于(假设 dstBuffer 有足够的空间):
while (srcBuffer.hasRemaining()) {
dstBuffer.put (srcBuffer.get());
}
public CharBuffer put(CharBuffer src)
-
Relative bulk
put method
(optional operation).
This method transfers the characters remaining in the given source buffer into this buffer. If there are more characters remaining in the source buffer than in this buffer, that is, ifsrc.remaining() > remaining(), then no characters are transferred and a
BufferOverflowException
is thrown.Otherwise, this method copies n = src.remaining() characters from the given buffer into this buffer, starting at each buffer's current position. The positions of both buffers are then incremented byn.
In other words, an invocation of this method of the form dst.put(src) has exactly the same effect as the loop
while (src.hasRemaining()) dst.put(src.get());
except that it first checks that there is sufficient space in this buffer and it is potentially much more efficient.
{
remaining
public final int remaining()
- Returns the number of elements between the current position and the limit.
-
-
Returns:
- The number of elements remaining in this buffer
hasRemaining
public final boolean hasRemaining()
- Tells whether there are any elements between the current position and the limit.
-
-
Returns:
- true if, and only if, there is at least one element remaining in this buffer
下面的 API 程序清单的最后两个函数中包含了两个只对 CharBuffer 适用的批量移动函数。
public abstract class CharBuffer
extends Buffer implements CharSequence, Comparable
{
// This is a partial API listing
public final CharBuffer put (String src)
public CharBuffer put (String src, int start, int end)
}
这些函数使用 String 作为参数,而且与作用于 char 数组的批量移动函数相似。如所有的java 程序员所知,
String 不同于 char 数组。但 String 确实包含 char 字符串,而且
我们人确实倾向于将其在概念上认为是 char 数组(尤其是我们中曾经是或者现在还是 C 或C++ 程序员的那些人)。 由于这些原因,CharBuffer 类提供了将 String 复制到
CharBuffer 中的便利方法。 String 移动与 char 数组移动相似,除了 在序列上是由 start 和end+1 下标确定(与String.subString()类似),而不是 start 下标和 length。所以:
buffer.put(myString);
等价于:
buffer.put(myString,0,myString.length);
而这就是您怎样复制字符 5 - 8,总共四个字符,从 myString 复制到 buffer。
buffer.put(myString,5,9);
public CharBuffer put(String src, int start, int end)
-
Relative bulk
put method
(optional operation).
This method transfers characters from the given string into this buffer. If there are more characters to be copied from the string than remain in this buffer, that is, ifend - start > remaining(), then no characters are transferred and a
BufferOverflowException
is thrown.Otherwise, this method copies n = end - start characters from the given string into this buffer, starting at the givenstart index and at the current position of this buffer. The position of this buffer is then incremented byn.
In other words, an invocation of this method of the form dst.put(src, start, end) has exactly the same effect as the loop
for (int i = start; i < end; i++) dst.put(src.charAt(i));
except that it first checks that there is sufficient space in this buffer and it is potentially much more efficient.
创建缓冲区:有七种主要的缓冲区类,每一种都具有一种 Java 语言中的非布尔类型的原始类型数据。(第 8 种MappedByteBuffer,是ByteBuffer 专门用于内存映射文件的一种特例)。这些类没有一种能够直接实例化。它们都是抽象类,但是都包含静态工厂方法用来创建相应类的新实例。
以CharBuffer 类为例!下面是创建一个缓冲区的关键函数,对所有的缓冲区类通用(要按照需要
替换类名):
public abstract class CharBuffer
extends Buffer implements CharSequence , Comparable
{
// This is a partial API listing
public static CharBuffer allocate (int capacity)
public static CharBuffer wrap (char [] array)
public static CharBuffer wrap (char [] array, int offset, int length)
public final boolean hasArray()
public final char [] array()
public final int arrayOffset()
}
新的缓冲区是由
分配或
包装操作创建的。分配操作创建一个缓冲区对象并分配一个私有的空间来储存容量大小的数据元素。
包装操作创建一个缓冲区对象但是不分配任何空间来储存数据元素。它使用您所提供的数组作为存储空间来储存缓冲区中的数据元素。
要分配一个容量为 100 个char 变量的 Charbuffer:
CharBuffer charBuffer = CharBuffer.allocate (100);
这段代码隐含地从
堆空间中分配了一个 char 型数组作为备份存储器来储存 100 个char变量。
如果您想提供您自己的数组用做缓冲区的备份存储器,请调用 wrap()函数:
char [] myArray = new char [100];
CharBuffer charbuffer = CharBuffer.wrap (myArray);
public static CharBuffer wrap(char[] array, int offset, int length)
-
Wraps a character array into a buffer.
The new buffer will be backed by the given character array; that is, modifications to the buffer will cause the array to be modified and vice versa. The new buffer's capacity will bearray.length, its position will beoffset, its limit will be offset + length, and its mark will be undefined. Its
backing array
will be the given array, and its
array offset
will be zero.
这个函数并不像您可能认为的那样,创建了一个只占用了一个数组子集的缓冲区。 这个缓冲区可以存取这个数组的全部范围;offset 和length 参数只是设置了初始的状态。调用使用上面代码中的方法创建的缓冲区中的 clear()函数,然后对其进行填充,直到超过上界值,这将会重写数组中的所有元素。
Slice()函数可以提供一个只占用备份数组一部分的缓冲区。
通过allocate() 或者wrap() 函数创建的缓冲区通常都是间接的,间接的缓冲区使用备份数组。Boolean 型函数 hasArray() 告诉您这个缓冲区是否有一个可存取的备份数组。如果这个函数的返回 true,array()函数会返回这个缓冲区对象所使用的数组存储空间的引用。
public final boolean hasArray()
-
Tells whether or not this buffer is backed by an accessible character array.
If this method returns true then the
array
andarrayOffset
methods may safely be invoked.
public final char[] array()
-
Returns the character array that backs this buffer
(optional operation).
Modifications to this buffer's content will cause the returned array's content to be modified, and vice versa.
Invoke the
hasArray
method before invoking this method in order to ensure that this buffer has an accessible backing array.
arrayOffset
public final int arrayOffset()
-
Returns the offset within this buffer's backing array of the first element of the buffer
(optional operation).
If this buffer is backed by an array then buffer position p corresponds to array indexp + arrayOffset().
Invoke the
hasArray
method before invoking this method in order to ensure that this buffer has an accessible backing array.
java.lang
Interface CharSequence
-
All Known Subinterfaces:
- Name
-
All Known Implementing Classes:
- CharBuffer, Segment, String, StringBuffer, StringBuilder
public interface CharSequence
A CharSequence is a readable sequence of char
values. This interface provides uniform, read-only access to many different kinds ofchar
sequences. Achar
value represents a character in theBasic Multilingual Plane (BMP) or a surrogate. Refer toUnicode Character Representation for details.
This interface does not refine the general contracts of the equals
andhashCode
methods. The result of comparing two objects that implementCharSequence is therefore, in general, undefined. Each object may be implemented by a different class, and there is no guarantee that each class will be capable of testing its instances for equality with those of the other. It is therefore inappropriate to use arbitraryCharSequence instances as elements in a set or as keys in a map.
CharBuffer charBuffer = CharBuffer.wrap ("Hello World");
复制缓冲区:------>>>>>>>暂缓介绍
复制一个缓冲区会创建一个新的 Buffer 对象,但并不复制数据。原始缓冲区和副本都会操作同样的数据元素。
缓冲区及其副本之间的联系如图所示。这是如下文所示的代码产生的:
CharBuffer buffer = CharBuffer.allocate(8);
buffer.position(3).limit(6).mark().position(5);
CharBuffer dupeBuffer = buffer.duplicate();
buffer.clear();
如果一个只读的缓冲区与一个可写的缓冲区共享数据,或者有包装好的备份数组,那么对这个可写的缓冲区或直接对这个数组的改变将反映在所有关联的缓冲区上,包括只读缓冲区。
字节缓冲区(ByteBuffer):所有的基本数据类型都有相应的缓冲区类(布尔型除外),但字节缓冲区有自己的独特之处。字节是操作系统及其I/O 设备使用的基本数据类型。当在JVM 和操作系统间传递数据时,将其他的数据类型拆分成构成它们的字节是十分必要的。系统层次的I/O 面向字节的性质可以在整个缓冲区的设计以及它们互相配合的服务中感受到。
Method Summary | |
---|---|
| allocate(int capacity) Allocates a new byte buffer. |
| allocateDirect(int capacity) Allocates a new direct byte buffer. |
array() Returns the byte array that backs this buffer (optional operation). | |
| arrayOffset() Returns the offset within this buffer's backing array of the first element of the buffer (optional operation). |
| asCharBuffer() Creates a view of this byte buffer as a char buffer. |
| asDoubleBuffer() Creates a view of this byte buffer as a double buffer. |
| asFloatBuffer() Creates a view of this byte buffer as a float buffer. |
| asIntBuffer() Creates a view of this byte buffer as an int buffer. |
| asLongBuffer() Creates a view of this byte buffer as a long buffer. |
| asReadOnlyBuffer() Creates a new, read-only byte buffer that shares this buffer's content. |
| asShortBuffer() Creates a view of this byte buffer as a short buffer. |
| compact() Compacts this buffer (optional operation). |
| compareTo(ByteBuffer that) Compares this buffer to another. |
| duplicate() Creates a new byte buffer that shares this buffer's content. |
| equals(Object ob) Tells whether or not this buffer is equal to another object. |
get() Relative get method. | |
| get(byte[] dst) Relative bulk get method. |
| get(byte[] dst, int offset, int length) Relative bulk get method. |
get(int index) Absolute get method. | |
getChar() Relative get method for reading a char value. | |
getChar(int index) Absolute get method for reading a char value. | |
getDouble() Relative get method for reading a double value. | |
getDouble(int index) Absolute get method for reading a double value. | |
getFloat() Relative get method for reading a float value. | |
getFloat(int index) Absolute get method for reading a float value. | |
getInt() Relative get method for reading an int value. | |
getInt(int index) Absolute get method for reading an int value. | |
getLong() Relative get method for reading a long value. | |
getLong(int index) Absolute get method for reading a long value. | |
getShort() Relative get method for reading a short value. | |
getShort(int index) Absolute get method for reading a short value. | |
| hasArray() Tells whether or not this buffer is backed by an accessible byte array. |
| hashCode() Returns the current hash code of this buffer. |
isDirect() Tells whether or not this byte buffer is direct. | |
| order() Retrieves this buffer's byte order. |
| order(ByteOrder bo) Modifies this buffer's byte order. |
| put(byte b) Relative put method (optional operation). |
| put(byte[] src) Relative bulk put method (optional operation). |
| put(byte[] src, int offset, int length) Relative bulk put method (optional operation). |
| put(ByteBuffer src) Relative bulk put method (optional operation). |
| put(int index, byte b) Absolute put method (optional operation). |
| putChar(char value) Relative put method for writing a char value (optional operation). |
| putChar(int index, char value) Absolute put method for writing a char value (optional operation). |
| putDouble(double value) Relative put method for writing a double value (optional operation). |
| putDouble(int index, double value) Absolute put method for writing a double value (optional operation). |
| putFloat(float value) Relative put method for writing a float value (optional operation). |
| putFloat(int index, float value) Absolute put method for writing a float value (optional operation). |
| putInt(int value) Relative put method for writing an int value (optional operation). |
| putInt(int index, int value) Absolute put method for writing an int value (optional operation). |
| putLong(int index, long value) Absolute put method for writing a long value (optional operation). |
| putLong(long value) Relative put method for writing a long value (optional operation). |
| putShort(int index, short value) Absolute put method for writing a short value (optional operation). |
| putShort(short value) Relative put method for writing a short value (optional operation). |
| slice() Creates a new byte buffer whose content is a shared subsequence of this buffer's content. |
| toString() Returns a string summarizing the state of this buffer. |
| wrap(byte[] array) Wraps a byte array into a buffer. |
| wrap(byte[] array, int offset, int length) Wraps a byte array into a buffer. |
Methods inherited from class java.nio.Buffer |
---|
capacity, clear, flip, hasRemaining, isReadOnly, limit, limit,mark, position, position, remaining, reset, rewind |
Methods inherited from class java.lang.Object |
---|
clone, finalize, getClass,notify, notifyAll, wait, wait, wait |
每个基本数据类型都是以连续字节序列的形式存储在内存中。尽管字节大小已经被确定,但字节顺序问题一直没有被广泛认同。表示一个整型值的字节可能在内存中仅仅如图 所示的那样被简单地排列。
多字节数值被存储在内存中的方式一般被称为 endian- ness(字节顺序)。如果数字数值的最高字节——big end(大端),位于低位地址,那么系统就是大端字节顺序。如果最低字节最先保存在内存中,那么小端字节顺序。
字节顺序很少由软件设计者决定;它通常取决于硬件设计。字节顺序的两种类型有时被称为字节性别,在当今被广泛使用。两种方式都具有自身的优势。Intel 处理器使用小端字节顺序设计。
在java.nio 中,字节顺序由 ByteOrder 类封装。 Java 的默认字节顺序是大端字节顺序。
package java.nio;
public final class ByteOrder
{
public static final ByteOrder BIG_ENDIAN
public static final ByteOrder LITTLE_ENDIAN
public static ByteOrder nativeOrd er( )
public String toString( )
}
很可能您会对为什么ByteBuffer 类需要一个字节顺序设定这一问题感到困惑。字节就是字节,对吗?当然,ByteBuffer 对象像其他基本数据类型一样,具有大量便利的函数用于获取和存放缓冲区内容。
这些函数对字节进行编码或解码的方式取决于 ByteBuffer 当前字节顺序的设定。
字节缓冲区跟其他缓冲区类型最明显的不同在于,它们可以成为通道所执行的I/O 的源头和/或目标。您会发现通道只接收 ByteBuffer 作为参数。
操作系统的在内存区域中进行I/O 操作。这些内存区域,就操作系统方面而言,是相连的字节序列。于是,毫无疑问,只有字节缓冲区有资格参与I/O 操作。也请回想一下操作系统会直接存取进程——在本例中是 JVM 进程的内存空间,以传输数据。这也意味着 I/O 操作的目标内存区域必须是连续的字节序列。在 JVM 中,字节数组可能不会在内存中连续存储,或者无用存储单元收集可能随时对其进行移动。在 Java 中,数组是对象,而数据存储在对象中的方式在不同的 JVM 实现中都各有不同。出于这一原因,引入了直接缓冲区的概念。
直接字节缓冲区通常是 I/O 操作最好的选择。在设计方面,它们支持 JVM 可用的最高效I/O 机制。非直接字节缓冲区可以被传递给通道,但是这样可能导致性能损耗。通常非直接缓冲不可能成为一个本地 I/O 操作的目标。如果您向一个通道中传递一个非直接 ByteBuffer对象用于写入,通道可能会在每次调用中隐含地进行下面的操作:
1.创建一个临时的直接 ByteBuffer 对象。
2.将非直接缓冲区的内容复制到临时缓冲中。
3.使用临时缓冲区执行低层次 I/O 操作。
4.临时缓冲区对象离开作用域,并最终成为被回收的无用数据。
直接缓冲区是I/O 的最佳选择,但可能比创建非直接缓冲区要花费更高的成本。直接缓冲区使用的内存是通过调用本地操作系统方面的代码分配的,绕过了标准JVM 堆栈。建立和销毁直接缓冲区会明显比具有堆栈的缓冲区更加破费,这取决于主操作系统以及JVM 实现。直接缓冲区的内存区域不受无用存储单元收集支配,因为它们位于标准 JVM 堆栈之外。 不过,以一条旧的软件行业格言建议您:
先使其工作,再加快其运行。不要一开始就过多担心优化问题;首先要注重正确性。
产生直接字节缓冲区:(注意用一个 wrap()函数所创建的被包装的缓冲区总是非直接的) 所有的缓冲区都提供了一个叫做 isDirect() 的boolean函数,来测试特定缓冲区是否
为直接缓冲区。
static ByteBuffer allocateDirect(int capacity)
//Allocates a new direct byte buffer.
视图缓冲区:在进行大数据量的I/O 操作时,很有可能您会使用各种 ByteBuffer 类去读取文件内容,接收来自网络连接的数据,等等。一旦数据到达了您的ByteBuffer ,您就需要查看它以决定怎么做或者在将它发送出去之前对它进行一些操作。ByteBuffer 类提供了丰富的API 来创建视图缓冲区。
视图缓冲区通过已存在的缓冲区对象实例的工厂方法来创建。这种视图对象维护它自己的属性,容量,位置,上界和标记,但是和原来的缓冲区共享数据元素。
ByteBuffer 类允许创建视图来将byte 型缓冲区字节数据映射为其它的原始数据类型。例如,asLongBuffer()函数创建一个将八个字节型数据当成一个 long 型数据来存取的视图缓冲区。
| asCharBuffer() Creates a view of this byte buffer as a char buffer. |
| asDoubleBuffer() Creates a view of this byte buffer as a double buffer. |
| asFloatBuffer() Creates a view of this byte buffer as a float buffer. |
| asIntBuffer() Creates a view of this byte buffer as an int buffer. |
| asLongBuffer() Creates a view of this byte buffer as a long buffer. |
| asReadOnlyBuffer() Creates a new, read-only byte buffer that shares this buffer's content. |
| asShortBuffer() Creates a view of this byte buffer as a short buffer. |
public abstract class ByteBuffer
extends Buffer implements Comparable
{
// This is a partial API listing
public abstract CharBuffer asCharBuffer( );
public abstract ShortBuffer asShortBuffer( );
public abstract IntBuffer asIntBuffer( );
public abstract LongBuffer asLongBuffer( );
public abstract FloatBuffer asFloatBuffer( );
public abstract DoubleBuffer asDoubleBuffer( );
}
新的缓冲区的容量是字节缓冲区中存在的元素数量除以视图类型中组成一个数据类型的字节数。
ByteBuffer byteBuffer = ByteBuffer.allocate(7).order(ByteOrder.BIG_ENDIAN);
CharBuffer charBuffer = byteBuffer.asCharBuffer();
package com.ronsoft.books.nio.buffers;
import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.ByteOrder;
/**
* Test asCharBuffer view.
*
* Created May 2002
*
* @author Ron Hitchens (ron@ronsoft.com)
*/
public class BufferCharView {
public static void main(String[] argv) throws Exception {
ByteBuffer byteBuffer = ByteBuffer.allocate(7).order(
ByteOrder.BIG_ENDIAN);
CharBuffer charBuffer = byteBuffer.asCharBuffer();
// Load the ByteBuffer with some bytes
byteBuffer.put(0, (byte) 0);
byteBuffer.put(1, (byte) 'H');
byteBuffer.put(2, (byte) 0);
byteBuffer.put(3, (byte) 'i');
byteBuffer.put(4, (byte) 0);
byteBuffer.put(5, (byte) '!');
byteBuffer.put(6, (byte) 0);
println(byteBuffer);
println(charBuffer);
}
// Print info about a buffer
private static void println(Buffer buffer) {
System.out.println("pos=" + buffer.position() + ", limit="
+ buffer.limit() + ", capacity=" + buffer.capacity() + ": '"
+ buffer.toString() + "'");
}
}
输出结果:
pos=0, limit=7, capacity=7: 'java.nio.HeapByteBuffer[pos=0 lim=7 cap=7]'
pos=0, limit=3, capacity=3: 'Hi!'
数据元素视图:ByteBuffer 类提供了一个不太重要的机制来以多字节数据类型的形式存取byte 数据组。ByteBuffer 类为每一种原始数据类型提供了存取的和转化的方法:
getChar(int index) Absolute get method for reading a char value. | |
getDouble() Relative get method for reading a double value. | |
getDouble(int index) Absolute get method for reading a double value. | |
getFloat() Relative get method for reading a float value. | |
getFloat(int index) Absolute get method for reading a float value. | |
getInt() Relative get method for reading an int value. | |
getInt(int index) Absolute get method for reading an int value. | |
getLong() Relative get method for reading a long value. | |
getLong(int index) Absolute get method for reading a long value. | |
getShort() Relative get method for reading a short value. | |
getShort(int index) Absolute get method for reading a short value. |
| putChar(char value) Relative put method for writing a char value (optional operation). |
| putChar(int index, char value) Absolute put method for writing a char value (optional operation). |
| putDouble(double value) Relative put method for writing a double value (optional operation). |
| putDouble(int index, double value) Absolute put method for writing a double value (optional operation). |
| putFloat(float value) Relative put method for writing a float value (optional operation). |
| putFloat(int index, float value) Absolute put method for writing a float value (optional operation). |
| putInt(int value) Relative put method for writing an int value (optional operation). |
| putInt(int index, int value) Absolute put method for writing an int value (optional operation). |
| putLong(int index, long value) Absolute put method for writing a long value (optional operation). |
| putLong(long value) Relative put method for writing a long value (optional operation). |
| putShort(int index, short value) Absolute put method for writing a short value (optional operation). |
| putShort(short value) Relative put method for writing a short value (optional operation). |
存取无符号数据 :Java 编程语言对无符号数值并没有提供直接的支持(除了 char 类型)。但是在许多情况下您需要将无符号的信息转化成数据流或者文件,或者包装数据来创建文件头或者其它带有无符号数据区域结构化的信息。ByteBuffer 类的 API 对此并没有提供直接的支持,但是要实现并不困难。您只需要小心精度的问题。当您必须处理缓冲区中的无符号数据时,下例中的工具类可能会非常有帮助。
//获取/存放无符号值的工具程序
package com.ronsoft.books.nio.buffers;
/*
模块考虑一个在用一个数除以另一个数时的余数。模块界限是对特定除数除数余数为零的数轴
上的点。例如,任何能够被4 均匀整除的数都是模块4 :4 ,8 ,12,16,等等。许多CPU 设计要求
模块内存的多字节数值排成直线。
*/
import java.nio.ByteBuffer;
/**
* 向ByteBuffer对象中获取和存放无符号值的工具类。 这里所有的函数都是静态的,并且带有一个ByteBuffer参数。 由于java
* 不提供无符号原始类型,每个从缓冲区中读出的无符号值被升到比它大的 下一个基本数据类型中。 getUnsignedByte()返回一个short类型,
* getUnsignedShort( )
*
* 返回一个int 类型,而getUnsignedInt()返回一个long 型。 There is no
* 由于没有基本类型来存储返回的数据,因此没有getUnsignedLong( ) 。 如果需要,返回BigInteger的函数可以执行。
* 同样,存放函数要取一个大于它们所分配的类型的值。 putUnsignedByte取一个short型参数,等等。
*
* @author Ron Hitchens (ron@ronsoft.com)
*/
public class Unsigned {
public static short getUnsignedByte(ByteBuffer bb) {
return ((short) (bb.get() & 0xff));
}
public static void putUnsignedByte(ByteBuffer bb, int value) {
bb.put((byte) (value & 0xff));
}
public static short getUnsignedByte(ByteBuffer bb, int position) {
return ((short) (bb.get(position) & (short) 0xff));
}
public static void putUnsignedByte(ByteBuffer bb, int position, int value) {
bb.put(position, (byte) (value & 0xff));
}
// ---------------------------------------------------------------
public static int getUnsignedShort(ByteBuffer bb) {
return (bb.getShort() & 0xffff);
}
public static void putUnsignedShort(ByteBuffer bb, int value) {
bb.putShort((short) (value & 0xffff));
}
public static int getUnsignedShort(ByteBuffer bb, int position) {
return (bb.getShort(position) & 0xffff);
}
public static void putUnsignedShort(ByteBuffer bb, int position, int value) {
bb.putShort(position, (short) (value & 0xffff));
}
// ---------------------------------------------------------------
public static long getUnsignedInt(ByteBuffer bb) {
return ((long) bb.getInt() & 0xffffffffL);
}
public static void putUnsignedInt(ByteBuffer bb, long value) {
bb.putInt((int) (value & 0xffffffffL));
}
public static long getUnsignedInt(ByteBuffer bb, int position) {
return ((long) bb.getInt(position) & 0xffffffffL);
}
public static void putUnsignedInt(ByteBuffer bb, int position, long value) {
bb.putInt(position, (int) (value & 0xffffffffL));
}
}
内存映射缓冲区:Mapped byte buffers are created via the FileChannel.map
method. This class extends the ByteBuffer
class with operations that are specific to memory-mapped file regions. 映射缓冲区通常是直接存取内存的,只能通过 FileChannel 类创建。映射缓冲区的用法和直接缓冲区类似,但是 MappedByteBuffer 对象可以处理独立于文件存取形式的的许多特定字符。