当前位置: 首页 > 技术随笔 > Java nio入门教程详解(九)

Java nio入门教程详解(九)

2.4.3 视图缓冲区

就像我们已经讨论的那样,I/O 基本上可以归结成组字节数据的四处传递。在进行大数据量的 I/O 操作时,很又可能您会使用各种ByteBuffer类去读取文件内容,接收来自网络连接的数据,等等。一旦数据到达了您的 ByteBuffer,您就需要查看它以决定怎么做或者在将它发送出去之前对它进行一些操作。ByteBuffer类提供了丰富的 API 来创建视图缓冲区。

视图缓冲区通过已存在的缓冲区对象实例的工厂方法来创建。这种视图对象维护它自己的属性,容量,位置,上界和标记,但是和原来的缓冲区共享数据元素。我们已经在 2.3 节见过了这样的简单例子,在例子中一个缓冲区被复制和切分。但是ByteBuffer类允许创建视图来将byte型缓冲区字节数据映射为其它的原始数据类型。例如,asLongBuffer()函数创建一个将八个字节型数据当成一个 long 型数据来存取的视图缓冲区。

下面列出的每一个工厂方法都在原有的ByteBuffer对象上创建一个视图缓冲区。调用其中的任何一个方法都会创建对应的缓冲区类型,这个缓冲区是基础缓冲区的一个切分,由基础缓冲区的位置和上界决定。新的缓冲区的容量是字节缓冲区中存在的元素数量除以视图类型中组成一个数据类型的字节数(参见表 2-1)。在切分中任一个超过上界的元素对于这个视图缓冲区都是不可见的。视图缓冲区的第一个元素从创建它的ByteBuffer对象的位置开始(positon()函数的返回值)。具有能被自然数整除的数据元素个数的视图缓冲区是一种较好的实现。

public abstract class ByteBuffer extends Buffer implements Comparable
{
// 这里仅列出部分API
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缓冲区的CharBuffer视图,如图 Figure 2-16所示(Example 2-2 将这个框架用到了更大的范围)

ByteBuffer byteBuffer = ByteBuffer.allocate (7).order(ByteOrder.BIG_ENDIAN);
CharBuffer charBuffer = byteBuffer.asCharBuffer();

图 2-16. 一个 ByteBuffer 的 CharBuffer 视图图 2-16. 一个 ByteBuffer 的 CharBuffer 视图

例 2-2. 创建一个 ByteBuffer 的字符视图

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

运行BufferCharView程序的输出是:

pos=0, limit=7, capacity=7: 'java.nio.HeapByteBuffer[pos=0 lim=7 cap=7]'
pos=0, limit=3, capacity=3: 'Hi!

一旦您得到了视图缓冲区,您可以用duplicate(), slice()asReadOnlyBuffer()函数创建进一步的子视图,就像 2.3 节所讨论的那样。

无论何时一个视图缓冲区存取一个ByteBuffer的基础字节,这些字节都会根据这个视图缓冲区的字节顺序设定被包装成一个数据元素。当一个视图缓冲区被创建时,视图创建的同时它也继承了基础ByteBuffer对象的字节顺序设定。这个视图的字节排序不能再被修改。在图 2-16 中,您可以看到基础ByteBuffer对象中的两个字节映射成CharBuffer对象中的一个字符。字节顺序设定决定了这些字节对是怎么样被组合成字符型变量的。请参考2.4.1 节获取更多详细的解释。

当直接从byte型缓冲区中采集数据时,视图换冲突拥有提高效率的潜能。如果这个视图的字节顺序和本地机器硬件的字节顺序一致,低等级的(相对于高级语言而言)语言的代码可以直接存取缓冲区中的数据值,而不是通过比特数据的包装和解包装过程来完成。

Java nio入门教程详解(十)

0 0
我们认为: 用户的主要目的,是为了获取有用的信息,而不是来点击广告的。因此本站将竭力做好内容,并将广告和内容进行分离,确保所有广告不会影响到用户的正常阅读体验。用户仅凭个人意愿和兴趣爱好点击广告。
我们坚信:只有给用户带来价值,用户才会给我们以回报。
CodePlayer技术交流群1CodePlayer技术交流群1

帮朋友打一个硬广告:

P2P网贷系统(Java版本) 新年低价大促销,多年P2P技术积累,系统功能完善(可按需定制,可支持第三方存管、银行存管),架构稳定灵活、性能优异、二次开发快速简单。 另可提供二次开发、安装部署、售后维护、安全培训等一条龙服务。

外行看热闹,内行看门道。可以自信地认为,在系统设计上,比市面上的晓风、迪蒙、方维、绿麻雀、国融信、金和盛等P2P系统要好。
深圳地区支持自带技术人员现场考察源代码、了解主要技术架构,货比三家,再决定是否购买。

也可推荐他人购买,一旦完全成交,推荐人可获得实际售价 10% 的返现。
有意向者,详情请 点击这里 联系,工作时间立即回复。