Java学习:NIO<一>
创始人
2024-02-20 19:16:40
0

NIO

    • 一、NIO概述
    • 二、Buffer

一、NIO概述

在JDK4中引入了NIO,可以最大限度的满足Java程序I/O的需求

  • java.nio包,定义了各种与buffer相关的类
  • java.nio.channel包,包含与Channel和Selector相关的类
  • java.nio.charset包,与字符集相关的类

在NIO中有三大核心组件:Channel、Buffer、Selector
传统IO与JavaNIO的区别:

IONIO
传统I/O是面向流的,每次可以从流中读取一个或多个字节,只能向后读取,不能向前移动;NIO是面向缓冲区的,把数据读取到一个缓冲区中,可以在缓冲区中向前/向后移动,增加了程序的灵活性
IO流是线程阻塞的,在调用read()/write()读写数据时,线程阻塞,直到数据读取完毕或者数据完全写入,在读取过程中,线程不能做其它操作;NIO不是线程阻塞的,当线程从Channel中读取数据时,如果通道中没有可用的数据,线程不阻塞,可以做其它的任务
/在NIO中,所有数据都需要通过Channel传输,通道可以直接将一块数据映射到内存中,channel是双向的,不仅可以读取数据,还能保存数据,程序不能直接读写channel通道,Channel只与Buffer缓冲区交互,数据通过channel写到buffer,程序从buffer中读数据

二、Buffer

  • Buffer缓冲区实际上就是一个数组,把数组的内容与信息包装成一个Buffer对象,提供了一组访问这些信息的方法

1、Buffer的属性

属性作用
capacity是指缓冲区可以存储多少个数据,容量在创建buffer缓冲区时指定大小,创建后不能再修改,如果缓冲区满了,需要清空后才能继续写数据
position表示当前位置,即缓冲区写入/读取的位置,刚刚创建Buffer对象后,position初始化为0,写入一个数据,position就向后移动一个单元,它的最大值为capacity - 1,当Buffer从写模式切换到读模式,position会被重置为0,每读一个数据,position就向后移动一个单元
limit是指第一个不能被读取或写入的位置,limit上限后面的单元既不能读也不能写,在Buffer缓冲区写模式下,limit表示能够写入多少个数据;在读取模式下,limit表示最多可以读取多少个数据
mark设置一个标记位置,可以调用mark()方法,把标记设置在position位置,当调用reset()方法时,就把position设置为mark标记的位置

2、Buffer的API

  • 在NIO关键的Buffer有:ByteBuffer、CharBuffer、DoubleBuffer、FloatBuffer、IntBuffer、LongBuffer、ShortBuffer,这些Buffer覆盖了能够通过I/O发送的所有基本类型:byte、char、double、float、int、long、short等。实际使用较多的是ByteBuffer、CharBuffer
API作用
allocate(capacity)可以创建一个指定容量的缓冲区
put()用于向缓冲区中存储数据
get()用于从缓冲区中读取数据
compact()当缓冲区还有未读完的数据,可以调用compact()方法进行压缩,将所有未读取的数据复制到Buffer的起始位置,把position设置到最后一个未读元素的后面。limit属性设置为capacity
capacity()返回缓冲区大小
limit()返回limit上限的位置
mark()设置缓冲区的标志位置,这个值只能在0 ~ position之间,以后可以通过reset()方法返回到这个位置
position()可以返回position当前位置
remaining()返回当前position位置与limit之间的数据量
rewind()将position设置为0,取消mark标志位
clear()清空缓冲区,仅仅是修改position标志为0,设置limit为capacity,缓冲区数据还是存在的
flip()可以把缓冲区由写模式切换到读模式,先把limit设置为position位置,再把position设置为0

3、案例
1)、创建buffer缓冲区

package JavaNIO;import java.nio.CharBuffer;
import java.util.Arrays;/*缓冲区的创建方式1)、分配操作创建缓冲区,allocate()分配一个私有的、指定容量大小的数组来存储元素2)、包装操作创建缓冲区,它使用提供的数组作为存储空间来存储缓冲区中的数据,不再分配其他空间*/
public class CreadBuffer {public static void main(String[] args) {//1)、分配操作创建缓冲区CharBuffer buffer = CharBuffer.allocate(16);//2)、包装操作创建缓冲区char[] myarray = new char[16];//把已存在的数组包装成一个buffer对象CharBuffer buffer1 = CharBuffer.wrap(myarray);//通过调用put方法向缓冲区中保存数据,也会直接影响到数组buffer1.put("hello");buffer1.flip();   //切换到读模式System.out.println(buffer1);System.out.println(Arrays.toString(myarray));//对数组做的任何修改,也会影响缓冲区对象/*不管是allocate()还是wrap()创建的缓冲区都是间接的,间接缓冲区会使用备份数组,hasArray()方法可以判断是否有一个可存取的备份数组如果hasArray()返回true,可以通过array()返回缓冲区对象使用的备份数组的引用备份数组的内容跟原始数组的内容是一致的*/if (buffer1.hasArray()){char[] arr2 = buffer1.array();System.out.println(Arrays.toString(arr2));}}
}

2)、相关API

package JavaNIO;import java.nio.CharBuffer;public class Buffer {public static void main(String[] args) {//1、创建CharBuffer缓冲区对象CharBuffer buffer = CharBuffer.allocate(12);//2、打印capacity,limit,positionSystem.out.println("capacity:" + buffer.capacity()+ ",limit:" + buffer.limit() + ",position:" + buffer.position());//capacity:12,limit:12,position:0//3、向缓冲区存储数据buffer.put('成');buffer.put('吉');buffer.put('思');buffer.put('汗');System.out.println("capacity:" + buffer.capacity()+ ",limit:" + buffer.limit() + ",position:" + buffer.position());//capacity:12,limit:12,position:4//4、调用filp()方法把缓冲区切换为读模式buffer.flip();System.out.println("capacity:" + buffer.capacity()+ ",limit:" + buffer.limit() + ",position:" + buffer.position());//capacity:12,limit:4,position:0//5、调用get()方法直接读取缓冲区数据System.out.println(buffer.get());System.out.println("capacity:" + buffer.capacity()+ ",limit:" + buffer.limit() + ",position:" + buffer.position());//capacity:12,limit:4,position:1//6、再次存储数据,把数据保存在position位置buffer.put('X');System.out.println("capacity:" + buffer.capacity()+ ",limit:" + buffer.limit() + ",position:" + buffer.position());//capacity:12,limit:4,position:2//7、设置标记buffer.mark();//8、再读取一个字符System.out.println(buffer.get());System.out.println("capacity:" + buffer.capacity()+ ",limit:" + buffer.limit() + ",position:" + buffer.position());//capacity:12,limit:4,position:3//9、调用reset(),把position重置为mark标记位置buffer.reset();System.out.println("capacity:" + buffer.capacity()+ ",limit:" + buffer.limit() + ",position:" + buffer.position());//capacity:12,limit:4,position:2//10、调用compact()压缩,会把postion后的数据移动到起始位置,limit重置为capacitybuffer.compact();System.out.println("capacity:" + buffer.capacity()+ ",limit:" + buffer.limit() + ",position:" + buffer.position());//11、调用clear清空buffer.clear();System.out.println("capacity:" + buffer.capacity()+ ",limit:" + buffer.limit() + ",position:" + buffer.position());//12、clear清空后,缓冲区的数据依然存在while (buffer.hasRemaining()){System.out.println(buffer.get());}}
}

3)、批量读取/写入

package JavaNIO;import java.nio.CharBuffer;
import java.util.Arrays;/*使用缓冲区就是为了提高数据传输效率,一次读写一个字符或一个字节效率并不高,可以进行批量的操作可以借助于数组,把缓冲区中的一块数据读取到数组中,也可以把数组中的部分内容保存到缓冲区中*/
public class BatchRead {public static void main(String[] args) {//创建CharBufferCharBuffer buffer = CharBuffer.allocate(15);buffer.put("云想衣裳花想容,春风拂槛露华浓");//切换为读模式buffer.flip();System.out.println(buffer);//定义字符数组char[] dst = new char[8];//调用get()方法把缓冲区中的数据读到字符数组中//注意批量传输时大小总是固定的,如果没有指定传输的大小,意味着把数组填满CharBuffer remainBuffer = buffer.get(dst);System.out.println(Arrays.toString(dst));//[云, 想, 衣, 裳, 花, 想, 容, ,],相当于把前8位写入字符数组中System.out.println(remainBuffer);//春风拂槛露华浓,后面再调用get()方法,剩余的就是remainBuffer//继续把buffer缓冲区的内容读到字符数组//buffer.get(dst);这时候是会报错的//当缓冲区的数据量不足以填满整个数组时,会抛出异常,剩下的是"春风拂槛露华浓",只有7个字符//此时可以调用get的重载,可以指定缓冲区长度buffer.get(dst,0,buffer.remaining());System.out.println(dst);}
}

相关内容

热门资讯

喜欢穿一身黑的男生性格(喜欢穿... 今天百科达人给各位分享喜欢穿一身黑的男生性格的知识,其中也会对喜欢穿一身黑衣服的男人人好相处吗进行解...
发春是什么意思(思春和发春是什... 本篇文章极速百科给大家谈谈发春是什么意思,以及思春和发春是什么意思对应的知识点,希望对各位有所帮助,...
网络用语zl是什么意思(zl是... 今天给各位分享网络用语zl是什么意思的知识,其中也会对zl是啥意思是什么网络用语进行解释,如果能碰巧...
为什么酷狗音乐自己唱的歌不能下... 本篇文章极速百科小编给大家谈谈为什么酷狗音乐自己唱的歌不能下载到本地?,以及为什么酷狗下载的歌曲不是...
家里可以做假山养金鱼吗(假山能... 今天百科达人给各位分享家里可以做假山养金鱼吗的知识,其中也会对假山能放鱼缸里吗进行解释,如果能碰巧解...
华为下载未安装的文件去哪找(华... 今天百科达人给各位分享华为下载未安装的文件去哪找的知识,其中也会对华为下载未安装的文件去哪找到进行解...
四分五裂是什么生肖什么动物(四... 本篇文章极速百科小编给大家谈谈四分五裂是什么生肖什么动物,以及四分五裂打一生肖是什么对应的知识点,希...
怎么往应用助手里添加应用(应用... 今天百科达人给各位分享怎么往应用助手里添加应用的知识,其中也会对应用助手怎么添加微信进行解释,如果能...
苏州离哪个飞机场近(苏州离哪个... 本篇文章极速百科小编给大家谈谈苏州离哪个飞机场近,以及苏州离哪个飞机场近点对应的知识点,希望对各位有...
客厅放八骏马摆件可以吗(家里摆... 今天给各位分享客厅放八骏马摆件可以吗的知识,其中也会对家里摆八骏马摆件好吗进行解释,如果能碰巧解决你...