java nio的学习-4

8 篇文章 0 订阅
7 篇文章 0 订阅

继续前文------->>>>>>>>>>>>>


压缩:因为不是常用的函数,所以



compact()
          Compacts this buffer  (optional operation).
暂时先不讲这一节。。。


标记:缓冲区四种属性中的三种。第四种,标记,使缓冲区能够记住一个位置并在之后将其返回。缓冲区的标记在mark(  ) 函数被调用之前是未定义的调用时标记被设为当前位置的值

public final Buffer mark()
Sets this buffer's mark at its position.
reset(   )函数将位置设为当前的标记值。如果标记值未定义,调用reset(  ) 将导致InvalidMarkException 异常。一些缓冲区函数会抛弃已经设定的标记(rewind(  ) ,clear(  ) ,以及flip(   ) 总是抛弃标记)。

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 aBufferUnderflowException 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 aBufferOverflowException 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 aBufferOverflowException 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. Itsbacking array will be the given array, and itsarray offset will be zero. 

这段代码构造了一个新的缓冲区对象,但数据元素会存在于数组中。这意味着通过调用put() 函数造成的对缓冲区的改动会直接影响这个数组,而且对这个数组的任何改动也会对这个缓冲区对象可见。
这个函数并不像您可能认为的那样,创建了一个只占用了一个数组子集的缓冲区。 这个缓冲区可以存取这个数组的全部范围;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.

如果一个缓冲区是只读的,它的备份数组将会是超出上界的,即使一个数组对象被提供给 wrap()函数。调用array()函数或者 arrayOffset() 会抛出一个 ReadOnlyBufferException 异常,来 阻止您得到存取权来修改只读缓冲区的内容。如果您通过其它的方式获得了 对备份数组的存取权限,对这个数组的修改也会直接影响到这个只读缓冲区。

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.

三个标准的实现了Charsequence 接口的类:String ,StringBuffer,和CharBuffer 。 所以String是只读的!!!因为其实现了CharSequence接口!

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).
比如说,如果 getInt()函数被调用,从当前的位置开始的四个字节会被包装成一个 int 类型的变量然后作为函数的返回值返回。如果您试图获取的原始类型需要比缓冲区中存在的字节数更多的字节,会抛出BufferUnderflowException。


存取无符号数据 :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 对象可以处理独立于文件存取形式的的许多特定字符。
























































  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值