Java NIO(二)-----Buffer
2021/9/20 12:35:41
本文主要是介绍Java NIO(二)-----Buffer,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
文章预览
- 前言
- 1、Java NIO简介
- 2、Buffer简介
- 一、Buffer的基本用法
- 1.1、基本步骤
- 1.2、使用 Buffer 的例子
- 1.3、 IntBuffer 的例子
- 1.4、Buffer 的 capacity、position 和 limit
- 1.5、Buffer 的类型
- 二、案例Demo
- 2.1、缓冲区分片
- 2.2、只读缓冲区
- 2.3、直接缓冲区
- 2.4、内存映射文件io
前言
1、Java NIO简介
Java NIO(New IO 或 Non Blocking IO)是从 Java 1.4 版本开始引入的一个新的
IO API,可以替代标准的 Java IO API。NIO 支持面向缓冲区的、基于通道的 IO 操
作。NIO 将以更加高效的方式进行文件的读写操作。
Java NIO 由以下几个核心部分组成:
Channels
Buffers
Selectors
虽然 Java NIO 中除此之外还有很多类和组件,但Channel
,Buffer
和Selector
构成
了核心的 API。其它组件,如Pipe
和FileLock
,只不过是与三个核心组件共同使用的
工具类。
这一节详细介绍一下Channel
,文章会持续更新
2、Buffer简介
Java NIO 中的 Buffer 用于和 NIO 通道进行交互。数据是从通道读入缓冲区,从缓冲区写入到通道中的。
缓冲区本质上是一块可以写入数据,然后可以从中读取数据的内存。这块内存被包装成 NIO Buffer
对象,并提供了一组方法,用来方便的访问该块内存。缓冲区实际上是
一个容器对象,更直接的说,其实就是一个数组,在 NIO 库中,所有数据都是用缓冲区处理的。在读取数据时,它是直接读到缓冲区中的; 在写入数据时,它也是写入到缓冲区中的;任何时候访问 NIO 中的数据,都是将它放到缓冲区中。而在面向流 I/O系统中,所有数据都是直接写入或者直接将数据读取到 Stream
对象中。在 NIO 中,所有的缓冲区类型都继承于抽象类 Buffer
,最常用的就是 ByteBuffer,对于 Java 中的基本类型,基本都有一个具体 Buffer
类型与之相对应,它们之间的继承关系如下图所示:
一、Buffer的基本用法
1.1、基本步骤
(1)写入数据到 Buffer
(2)调用 flip()
方法
(3)从 Buffer
中读取数据
(4)调用 clear()
方法或者 compact()
方法
当向 buffer
写入数据时,buffer
会记录下写了多少数据。一旦要读取数据,需要通过flip()
方法将 Buffer
从写模式切换到读模式。在读模式下,可以读取之前写入到 buffer
的所有数据。一旦读完了所有的数据,就需要清空缓冲区,让它可以再次被写入。有两种方式能清空缓冲区:调用 clear()
或 compact()
方法。clear()
方法会清空整个缓冲
区。compact()
方法只会清除已经读过的数据。任何未读的数据都被到缓冲区的起始处,新写入的数据将放到缓冲区未读数据的后面。
1.2、使用 Buffer 的例子
@Test public void buffer01() throws Exception { //FileChannel RandomAccessFile aFile = new RandomAccessFile("d:\\atguigu\\01.txt","rw"); FileChannel channel = aFile.getChannel(); //创建buffer,大小 ByteBuffer buffer = ByteBuffer.allocate(1024); //读 int bytesRead = channel.read(buffer); while(bytesRead != -1) { //read模式 buffer.flip(); while(buffer.hasRemaining()) { System.out.println((char)buffer.get()); } buffer.clear(); bytesRead = channel.read(buffer); } aFile.close(); }
1.3、 IntBuffer 的例子
@Test public void buffer02() throws Exception { //创建buffer IntBuffer buffer = IntBuffer.allocate(8); //buffer放 for (int i = 0; i < buffer.capacity(); i++) { int j = 2*(i+1); buffer.put(j); } //重置缓冲区 buffer.flip(); //获取 while(buffer.hasRemaining()) { int value = buffer.get(); System.out.println(value+" "); } }
1.4、Buffer 的 capacity、position 和 limit
为了理解 Buffer 的工作原理,需要熟悉它的三个属性:
Capacity
Position
limit
position
和 limit
的含义取决于 Buffer
处在读模式还是写模式。不管 Buffer
处在什么模式,capacity
的含义总是一样的。
这里有一个关于 capacity
,position
和 limit
在读写模式中的说明
(1)capacity
作为一个内存块,Buffer 有一个固定的大小值,也叫“capacity
”.你只能往里写capacity 个 byte、long,char
等类型。一旦 Buffer 满了,需要将其清空(通过读数据或者清除数据)才能继续写数据往里写数据。
(2)position
1)写数据到 Buffer 中时,position
表示写入数据的当前位置,position
的初始值为0。当一个 byte、long 等数据写到 Buffer 后, position
会向下移动到下一个可插入数据的 Buffer 单元。position 最大可为 capacity – 1(因为 position 的初始值为0).
2)读数据到 Buffer 中时,position
表示读入数据的当前位置,如 position=2 时表示已开始读入了 3 个 byte,或从第 3 个 byte 开始读取。通过 ByteBuffer.flip()
切换到读模式时 position 会被重置为 0,当 Buffer
从 position
读入数据后,position 会下移到下一个可读入的数据 Buffer 单元。
(3)limit
1)写数据时,limit
表示可对 Buffer 最多写入多少个数据。写模式下,limit 等于Buffer 的 capacity。
2)读数据时,limit
表示 Buffer
里有多少可读数据(not null 的数据),因此能读到之前写入的所有数据(limit 被设置成已写数据的数量,这个值在写模式下就是position
)。
1.5、Buffer 的类型
Java NIO 有以下 Buffer 类型
- ByteBuffer
- MappedByteBuffer
- CharBuffer
- DoubleBuffer
- FloatBuffer
- IntBuffer
- LongBuffer
- ShortBuffer
这些 Buffer 类型代表了不同的数据类型。换句话说,就是可以通过 char,short,int,long,floa
t 或 double
类型来操作缓冲区中的字节。
二、案例Demo
2.1、缓冲区分片
ByteBuffer slice = buffer.slice();
创建分片,即子缓冲区
@Test public void b01() { ByteBuffer buffer = ByteBuffer.allocate(10); for (int i = 0; i < buffer.capacity(); i++) { buffer.put((byte)i); } //创建子缓冲区 buffer.position(3); buffer.limit(7); ByteBuffer slice = buffer.slice(); //改变子缓冲区内容 for (int i = 0; i <slice.capacity() ; i++) { byte b = slice.get(i); b *=10; slice.put(i,b); } buffer.position(0); buffer.limit(buffer.capacity()); while(buffer.remaining()>0) { System.out.println(buffer.get()); } }
2.2、只读缓冲区
创建只读缓冲区
ByteBuffer readonly = buffer.asReadOnlyBuffer();
//只读缓冲区 @Test public void b02() { ByteBuffer buffer = ByteBuffer.allocate(10); for (int i = 0; i < buffer.capacity(); i++) { buffer.put((byte)i); } //创建只读缓冲区 ByteBuffer readonly = buffer.asReadOnlyBuffer(); for (int i = 0; i < buffer.capacity(); i++) { byte b = buffer.get(i); b *=10; buffer.put(i,b); } readonly.position(0); readonly.limit(buffer.capacity()); while (readonly.remaining()>0) { System.out.println(readonly.get()); } }
2.3、直接缓冲区
创建直接缓冲区
ByteBuffer buffer = ByteBuffer.allocateDirect(1024);
@Test public void b03() throws Exception { String infile = "d:\\atguigu\\01.txt"; FileInputStream fin = new FileInputStream(infile); FileChannel finChannel = fin.getChannel(); String outfile = "d:\\atguigu\\02.txt"; FileOutputStream fout = new FileOutputStream(outfile); FileChannel foutChannel = fout.getChannel(); //创建直接缓冲区 ByteBuffer buffer = ByteBuffer.allocateDirect(1024); while (true) { buffer.clear(); int r = finChannel.read(buffer); if(r == -1) { break; } buffer.flip(); foutChannel.write(buffer); } }
2.4、内存映射文件io
@Test public void b04() throws Exception { RandomAccessFile raf = new RandomAccessFile("d:\\atguigu\\01.txt", "rw"); FileChannel fc = raf.getChannel(); MappedByteBuffer mbb = fc.map(FileChannel.MapMode.READ_WRITE, start, size); mbb.put(0, (byte) 97); mbb.put(1023, (byte) 122); raf.close(); }
这篇关于Java NIO(二)-----Buffer的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-23Springboot应用的多环境打包入门
- 2024-11-23Springboot应用的生产发布入门教程
- 2024-11-23Python编程入门指南
- 2024-11-23Java创业入门:从零开始的编程之旅
- 2024-11-23Java创业入门:新手必读的Java编程与创业指南
- 2024-11-23Java对接阿里云智能语音服务入门详解
- 2024-11-23Java对接阿里云智能语音服务入门教程
- 2024-11-23JAVA对接阿里云智能语音服务入门教程
- 2024-11-23Java副业入门:初学者的简单教程
- 2024-11-23JAVA副业入门:初学者的实战指南