NIO 01 NIO概述

1、NIO

JDK1.4出现的新的IO (New IO) API
有三个重要的组成部分:
缓冲区(Buffer)、通道(Channel)、选择器(Selector)
缓冲区用于存储数据,通道用于传输数据,选择器用于监控数据

2、Buffer(缓冲区)

⑴ 一个用于特定基本数据类型的容器

一共有7种(除了boolean类型):
ByteBuffer
ShortBuffer
IntBuffer
LongBuffer
FloatBuffer
DoubleBuffer
CharBuffer

⑵ 属性

limit 限制,第一个不应该读取或写入的元素的索引。不能为负数,且不能大于其容量

position 位置,下一个要读取或写入的元素的索引。不能为负数,且不能大于其容量

capacity 容量,缓冲区包含的元素的数量。不能为负数,且一旦指定后将不能更改

⑶ mark、limit、position、capacity

0 <= mark <= limit <= position <= capacity

⑷ API

⒈ allocate
public static ByteBuffer allocate(int capacity) {}
静态方法,以ByteBuffer为例,创建非直接缓冲区

⒉ allocateDirect
public static ByteBuffer allocateDirect(int capacity) {}
静态方法,以ByteBuffer为例,创建直接缓冲区

    Tips:如果创建了直接缓冲区,则JVM会尽最大努力直接在此缓冲区上进行I/O操作,会尽量避免将缓冲区的内容复制到中间缓存区中

    注意:建议将直接缓冲区主要分配给那些易受基础系统的本机I/O操作影响的大型的、持久的缓冲区。一般仅在使用直接缓冲区能给程序性能方面带来明显好处时分配

⒊ flip
切换为读取数据模式

⒋ rewind
可以重复读取数据

⒌ clear
清空缓冲区,limit变为capacity大小(不能操作的索引位置),position变为0(下一个可以操作的位置)。但是里面的数据还存在

⒍ mark
标记position位置(下一个可以操作的索引位置)

⒎ reset
回退到mark标记的position位置

3、Channel(通道)

⑴ 用于源节点和目标节点的连接

在NIO中负责数据的传输。它本身不存储数据,需要配合缓冲区来使用

⑵有四个主要的实现类

FileChannel

SocketChannel
ServerSocketChannel
DatagramChannel

⑶ 获取方式

⒈ 方式一

FileInputStream 或 FileOutputStream 或 RandomAccessFile 的getChannel方法

Socket 或 ServeSocket 或 DatagramSocket的getChannel方法

⒉ 方式二【JDK7】

  对应类型的静态的open方法
    public static FileChannel open(Path path, OpenOption… options) {}
    第一个参数为路径,通过Paths.get(“”)方法来获取文件路径。之后是可变参数,使用StandardOpenOption枚举类来指定是读、写还是其他

    public static Path get(String first, String… more) {}
     获取路径
      StandardOpenOption.READ 读模式
      StandardOpenOption.WRITE 写模式
      StandardOpenOption.CREATE_NEW 创建新文件(如果文件已经存在,再次创建时会报错)
      StandardOpenOption.CREATE 覆盖文件

3.方式三【JDK7】

    Files.newByteChannel方法

⑷ 直接缓冲区

    MappedByteBuffer 通过FileChannel的map方法获取
      MappedByteBuffer map(MapMode mode, long position, long size)
      第一个参数是映射的模式,通过MapMode的常量来指定是只读还是读写;第二个参数是起始位置(从0开始);第三个参数是要映射的区域大小,通过FileChannel的size方法获取【注意是读取通道】

  相关方法:
    ⒈ get
       public ByteBuffer get(byte[] dst) {}
      将直接缓冲区中读取到的数据放到byte数组中

    ⒉ put
       public final ByteBuffer put(byte[] src) {}
      将字节数据中的数据输出到缓冲区中

⑸ Channel的API

⒈ transferTo
    long transferTo(long position, long count, WritableByteChannel target) {}
    将可读通道中的数据传输给指定的可写通道。返回实际传输的字节大小,可能为0【通过读取通道调用】

⒉ transferFrom
    long transferFrom(ReadableByteChannel src, long position, long count)
    将指定的可读通道中的数据传输给此可写通道。返回实际传输的字节大小,可能为0【通过写出通道调用】

⒊ read(ByteBuffer[] dsts)
    分散读取

⒋ write(ByteBuffer[] srcs)
    聚集写入。注意:写入前,需要将所有的缓冲区开启读取模式(遍历调用flip方法)

4、字符缓冲区(CharBuffer)

⑴ 字符对象、字符编码器和解码器

⒈ Charset.forName(“编码集”)
    获取指定编码集的Charset对象

⒉ 获取编码器和解码器
    调用Charset对象的
        CharsetEncoder newEncoder();
        CharsetDecoder newDecoder();
    方法

⒊ 编码
    调用CharsetEncoder的encode方法
        ByteBuffer encode(CharBuffer in) {}

⒋ 解码
    调用CharsetDecoder的decode方法
        CharBuffer decode(ByteBuffer in) {}

⑵ 示例

    Charset charset = Charset.forName("UTF-8");
    CharsetEncoder encoder = charset.newEncoder();
    CharsetDecoder decoder = charset.newDecoder();

    CharBuffer charBuffer = CharBuffer.allocate(1024);
    charBuffer.put("你好!");
    charBuffer.flip();

    try {
        ByteBuffer byteBuffer = encoder.encode(charBuffer);

        CharBuffer buffer = decoder.decode(byteBuffer);
        System.out.println(buffer);
    } catch (CharacterCodingException e) {
        e.printStackTrace();
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值