NIO笔记1_NIO简介与缓冲区Buffer

Java NIO 简介

Java NIO(New IO)是从Java 1.4版本开始引入的一个新的IOAPI,可以替代标准的Java IO API。NIO与原来的IO有同样的作用和目的,但是使用的方式完全不同,NIO支持面向缓冲区的、基于通道的IO操作。NIO将以更加高效的方式进行文件的读写操作。

Java NIO 与IO 的主要区别

通道和缓冲区

Java NIO系统的核心在于:通道(Channel)和缓冲区(Buffer)。通道表示打开到IO 设备(例如:文件、套接字)的连接。若需要使用NIO 系统,需要获取用于连接IO设备的通道以及用于容纳数据的缓冲区。然后操作缓冲区,对数据进行处理。

简而言之,Channel 负责传输,Buffer 负责存储

缓冲区(Buffer)

缓冲区(Buffer):一个用于特定基本数据类型的容器。由java.nio 包定义的,所有缓冲区都是Buffer 抽象类的子类。

Java NIO中的Buffer 主要用于与NIO 通道进行交互,数据是从通道读入缓冲区,从缓冲区写入通道中的。

Buffer 就像一个数组,可以保存多个相同类型的数据。根据数据类型不同(boolean 除外) ,有以下Buffer 常用子类:

ByteBuffer

CharBuffer

ShortBuffer

IntBuffer

LongBuffer

FloatBuffer

DoubleBuffer

上述Buffer 类他们都采用相似的方法进行管理数据,只是各自管理的数据类型不同而已。都是通过如下方法获取一个Buffer 对象:

static XxxBuffer allocate(int capacity) : 创建一个容量为capacity的XxxBuffer 对象

缓冲区的基本属性

Buffer 中的重要概念:

容量(capacity) :表示Buffer 最大数据容量,缓冲区容量不能为负,并且创建后不能更改。

限制(limit):第一个不应该读取或写入的数据的索引,即位于limit 后的数据不可读写。缓冲区的限制不能为负,并且不能大于其容量。

位置(position):下一个要读取或写入的数据的索引。缓冲区的位置不能为负,并且不能大于其限制

标记(mark)与重置(reset):标记是一个索引,通过Buffer中的mark() 方法指定Buffer 中一个特定的position,之后可以通过调用reset() 方法恢复到这个position.

标记、位置、限制、容量遵守以下不变式:0<=mark<=position<=limit<=capacity

Buffer 的常用方法

缓冲区的数据操作

Buffer 所有子类提供了两个用于数据操作的方法:get()与put() 方法

获取Buffer 中的数据

get() :读取单个字节

get(byte[] dst):批量读取多个字节到dst中

get(int index):读取指定索引位置的字节(不会移动position)

放入数据到Buffer 中

put(byte b):将给定单个字节写入缓冲区的当前位置

put(byte[] src):将src 中的字节写入缓冲区的当前位置

put(int index, byte b):将指定字节写入缓冲区的索引位置(不会移动position)

//示例一
	@Test
	public void test1(){
		String str = "abcde";
		
		//1. 分配一个指定大小的缓冲区
		ByteBuffer buf = ByteBuffer.allocate(1024);
		
		System.out.println("-----------------allocate()----------------");
		System.out.println(buf.position());
		System.out.println(buf.limit());
		System.out.println(buf.capacity());
		
		//2. 利用 put() 存入数据到缓冲区中
		buf.put(str.getBytes());
		
		System.out.println("-----------------put()----------------");
		System.out.println(buf.position());
		System.out.println(buf.limit());
		System.out.println(buf.capacity());
		
		//3. 切换读取数据模式
		buf.flip();
		
		System.out.println("-----------------flip()----------------");
		System.out.println(buf.position());
		System.out.println(buf.limit());
		System.out.println(buf.capacity());
		
		//4. 利用 get() 读取缓冲区中的数据
		byte[] dst = new byte[buf.limit()];
		buf.get(dst);
		System.out.println(new String(dst, 0, dst.length));
		
		System.out.println("-----------------get()----------------");
		System.out.println(buf.position());
		System.out.println(buf.limit());
		System.out.println(buf.capacity());
		
		//5. rewind() : 可重复读
		buf.rewind();
		
		System.out.println("-----------------rewind()----------------");
		System.out.println(buf.position());
		System.out.println(buf.limit());
		System.out.println(buf.capacity());
		
		//6. clear() : 清空缓冲区. 但是缓冲区中的数据依然存在,但是处于“被遗忘”状态
		buf.clear();
		
		System.out.println("-----------------clear()----------------");
		System.out.println(buf.position());
		System.out.println(buf.limit());
		System.out.println(buf.capacity());
		
		System.out.println((char)buf.get());
		
	}
//示例二
	@Test
	public void test2(){
		String str = "abcde";
		
		ByteBuffer buf = ByteBuffer.allocate(1024);
		
		buf.put(str.getBytes());
		
		buf.flip();
		
		byte[] dst = new byte[buf.limit()];
		buf.get(dst, 0, 2);
		System.out.println(new String(dst, 0, 2));
		System.out.println(buf.position());
		
		//mark() : 标记
		buf.mark();
		
		buf.get(dst, 2, 2);
		System.out.println(new String(dst, 2, 2));
		System.out.println(buf.position());
		
		//reset() : 恢复到 mark 的位置
		buf.reset();
		System.out.println(buf.position());
		
		//判断缓冲区中是否还有剩余数据
		if(buf.hasRemaining()){
			
			//获取缓冲区中可以操作的数量
			System.out.println(buf.remaining());
		}
	}


猜你喜欢

转载自blog.csdn.net/zhuzhufxz/article/details/80041912
今日推荐