Java 缓冲区续:字节缓冲区

来源:互联网 发布:郑州家装设计师 知乎 编辑:程序博客网 时间:2024/05/03 06:54

1 字节缓冲区API 

   所有基本类型(除布尔)都有相应缓冲区,但字节缓冲区有自己的独特之处。字节是操作系统以及IO使用的基本类型。当在JVM和操作系统间传递数据时,将其他的数据类型拆分成他们的字节是十分必要的。

package java.nio;    public abstract class ByteBuffer extends Buffer          implements Comparable  {          public static ByteBuffer allocate (int capacity)          public static ByteBuffer allocateDirect (int capacity)          public abstract boolean isDirect(  );           public static ByteBuffer wrap (byte[] array, int offset, int length)          public static ByteBuffer wrap (byte[] array)            public abstract ByteBuffer duplicate(  );          public abstract ByteBuffer asReadOnlyBuffer(  );          public abstract ByteBuffer slice(  );           public final boolean hasArray(  )          public final byte [] array(  )          public final int arrayOffset(  )            public abstract byte get(  );          public abstract byte get (int index);          public ByteBuffer get (byte[] dst, int offset, int length)          public ByteBuffer get (byte[] dst, int offset, int length)            public abstract ByteBuffer put (byte b);          public abstract ByteBuffer put (int index, byte b);          public ByteBuffer put (ByteBuffer src)          public ByteBuffer put (byte[] src, int offset, int length)          public final ByteBuffer put (byte[] src)            public final ByteOrde r order(  )           public final ByteBuffer order (ByteOrder bo)     public abstract CharBuffer asCharBuffer(  );       public abstract ShortBuffer asShortBuffer(  );      public abstract IntBuffer asIntBuffer(  );       public abstract LongBuffer asLongBuffer(  );      public abstract FloatBuffer asFloatBuffer(  );       public abstract DoubleBuffer asDoubleBuffer(  );       public abstract char getChar(  );      public abstract char getChar (int index);      public abstract ByteBuffer putChar (char value);      public abstract ByteBuffer putChar (int index, char value);      public abstract short getShort(  );        public abstract short getShort (int index);      public abstract ByteBuffer putShort (short value);      public abstract ByteBuffer putShort (int index, short value);      public abstract int getInt(  );      public abstract int getInt (int index);      public abstract ByteBuffer putInt (int value);      public abstract ByteBuffer putInt (int index, int value);       public abstract long getLong(  );      public abstract long getLong (int index);      public abstract ByteBuffer putLong (long value);      public abstract ByteBuffer putLong (int index, long value);      public abstract float getFloat(  );      public abstract float getFloat (int index);      public abstract ByteBuffer putFloat (float value);      public abstract ByteBuffer putFloat (int index, float value);         public abstract double getDouble(  );      public abstract double getDouble (int index);      public abstract ByteBuffer putDouble (double value);      public abstract ByteBuffer putDouble (int index, double value);         public abstract ByteBuffer compact(  );      public boolean equals (Object ob) {      public int compareTo (Object ob) {      public String toString(  )       public int hashCode(  ) }

2 字节顺序   

     每个基本数据类型都是以连续字节序列的形式存储在内中。尽管字节大小已经确定,但字节顺序问题一直没有被广泛认同。

    多字节数值被存储在内存中的方式一般被称为endian-ness。如果数字数值的最高字节(big end),位于低位地址,那么系统就是大端字节顺序。
如果最低字节最先保存在内中,那么小端字节顺序。
    字节顺序的问题通常取决于硬件的设计。字节顺序的两种类型有时被称为字节性别。Intel处理器使用小端字节顺序。
    IP协议规定使用大端的网络字节顺序,所有在IP分组报文的协议部分中使用的多字节数值必须在本地主机字节顺序和通用的网络字节顺序之间进

行转换。    

package java.nio;    public final class ByteOrder  {          public static final ByteOrder BIG_ENDIAN          public static final ByteOrder LITTLE_ENDIAN            public static ByteOrder nativeOrder(  )          public String toString(  )  }
    ByteOrder类定义了决定从缓冲区中存储或检索多个字节数值时使用哪一字节顺序的常量。
    ByteBuffer类有所不同:默认字节顺序总是大端字节顺序,无论系统的固有字节顺序是什么。Java的默认字节顺序是大端字节顺序,这允许类文件等以及串行化的对象可以在任何JVM中工作。
    ByteBuffer的字符顺序设定可以随时通过调用以下方法来改变:   
public abstract class ByteBuffer extends Buffer          implements Comparable  {          // This is a partial API listing            public final ByteOrder order(  )          public final ByteBuffer order (ByteOrder bo)  }
    视图的字节顺序设定在创建后不能被改变,而且如果原始的字节缓冲区的字节顺序在之后被改变,它也不会受到影响

3 直接缓冲区

    字节缓冲区与其他缓冲区最明显的不同在于,它可以成为通道所执行的IO的源或目标。操作系统在内存区域中进行IO操作,在内存区域,就操作
系统而言,就是相连的字节序列。于是,只有字节缓冲区有资格参与IO操作。在JVM中,字节数组可能不会在内存中连续存储,或者无用存储单元收集
可能随时对其进行移动。出于这一原因,引入直接缓冲区,用来与通道和固有IO例程交互。
    非直接字节缓冲区可以被传递给通道,这样做会导致性能损耗。如果向一个通道中传递一个非直接ByteBuffer对象用于写入,通道可能会在每次
调用中隐含进行一下操作:
    1 创建临时的直接ByteBuffer对象
    2 将非直接缓冲区的内容复制到临时缓冲区
    3 使用临时缓冲区执行低层次IO操作。
    4 临时缓冲区对象离开作用域,并最终成为被回收的无用数据。
    这可能导致缓冲区在每个IO上复制并产生大量对象。直接缓冲区是IO的最佳选择,但比创建非直接缓冲区成本更高。直接缓冲区使用的内存是通
过调用本地操作系统的代码分配的,绕过了JVM堆栈。
    直接 ByteBuffer 是通过调用具有所需容量的 ByteBuffer.allocateDirect()方法产生的。

public abstract class ByteBuffer          extends Buffer implements Comparable   {          // This is a partial API listing         public static ByteBuffer allocate (int capacity)          public static ByteBuffer allocateDirect (int capacity)          public abstract boolean isDirect(  );  }
    ByteBuffer 是唯一可以被直接分配的类型,但如果基础缓冲区是一个直接 ByteBuffer,对于非字节视图缓冲区,isDirect()可以是 true

4 视图缓冲区

    视图缓冲区通过已存在的缓冲区对象实例的工厂方法来创建,它维护自己的属性、容量、位置、上界和标记,但与原来的缓冲区共享数据元素。
    ByteBuffer提供了多个工厂方法来创建其他类型视图缓冲区,这些缓冲区是基础缓冲区的一个切分,由基础缓冲区的位置和上界决定。新的缓冲区的容量是字节缓冲区中存在的元素量除以视图类型中组成一个数据类型的字节数。
    无论何时一个视图缓冲区存取一个 ByteBuffer 的基础字节,这些字节都会根据这个视图缓冲区的字节顺序设定被包装成一个数据元素。当一个视图缓冲区被创建时,视图创建的同时它也继承了基础 ByteBuffer 对象的字节顺序设定。

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(  );  }

5 数据元素视图

    ByteBuffer类提供了一种轻量级的机制,可以将字节组合作为多字节的数据类型来存取。

public abstract class ByteBuffer          extends Buffer implements Comparable   {          public abstract char getChar(  );          public abstract char getChar (int index);          public abstract short getShort(  );          public abstract short getShort (int index);          public abstract int getInt(  );          public abstract int getInt (int index);          public abstract long getLong(  );          public abstract long getLong (int index);          public abstract float getFloat(  );          public abstract float getFloat (int index);          public abstract double getDouble(  );          public abstract double getDouble (int index);            public abstract ByteBuffer putChar (char value);          public abstract ByteBuffer putChar (int index, char value);          public abstract ByteBuffer putShort (short value);          public abstract ByteBuffer putShort (int index, short value);          public abstract ByteBuffer putInt (int value);          public abstract ByteBuffer putInt (int index, int value);          public abstract ByteBuffer putLong (long value);          public abstract ByteBuffer putLong (int index, long value);          public abstract ByteBuffer putFloat (float value);          public abstract ByteBuffer putFloat (int index, float value);          public abstract ByteBuffer putDouble (double value);          public abstract ByteBuffer putDouble (int index, double value);  }
    这些方法从当前位置开始存取 ByteBuffer 的字节数据,就好像一个数据元素被存储在那里一样,据这个缓冲区的当前的有效的字节顺序,这些
字节数据会被排列或打乱成需要的原始数据类型。
    int value = buffer.getInt( ); 
    返回一个由缓冲区中位置 1-4 的 byte 数据值组成的 int 型变量的值。实际的返回值取决于缓冲区的当前的字节顺序(byte-order)设置,更
具体的写法是:
    int value = buffer.order (ByteOrder.BIG_ENDIAN).getInt( );

6 存取无符号数据 

    Java 编程语言对无符号数值并没有提供直接的支持。但是可以通过以下方法实现:    
public static short getUnsignedByte (ByteBuffer bb)      {          return ((short)(bb.get(  ) & 0xff));      }

7 内存映射缓冲区

    映射缓冲区是与文件存储的数据元素关联的字节缓冲区,它通过内存映射来访问。映射缓冲区通常是直接存取内存的,只能通过 FileChannel 类
创建。映射缓冲区的用法和直接缓冲区类似,但是 MappedByteBuffer 对象具有许多文件存取独有的特征。




原创粉丝点击