Java NIO 频道

Java NIO渠道类似于流,他们之间具有一些区别的:

  • 您可以读取和写入频道。流通常是单向(读或写)。
  • 通道可以异步读取和写入数据。
  • 通道常常是读取或写入缓冲区。

如上所述,您将数据从通道读入缓冲区,并将数据从缓冲区写入通道。以下是流程图:

Java NIO:Channels read data into Buffers, and Buffers write data into Channels

Channel 的实现

以下是Java NIO中最重要的Channel实现:

  • FileChannel
  • DatagramChannel
  • SocketChannel
  • ServerSocketChannel

FileChannel--------从文件中读取和读入数据。

DatagramChannel----可以通过UDP网络读取和写入数据。

SocketChannel------可以通过TCP网络读取和写入数据。

ServerSocketChannel---让您监听进入的TCP连接,例如Web服务器一样。对于每个传入连接 SocketChannel都创建。

简单的Channel示例

这是使用一个FileChannel将一些数据读取到一个Buffer的简单示例

RandomAccessFile aFile = new RandomAccessFile(“data / nio-data.txt”,“rw”);
FileChannel inChannel = aFile.getChannel(); ByteBuffer buf = ByteBuffer.allocate(48); int bytesRead = inChannel.read(buf);
while(bytesRead!= -1){ System.out.println(“Read”+ bytesRead);
buf.flip();
while(buf.hasRemaining()){
System.out.print((char)buf.get());
}
buf.clear();
bytesRead = inChannel.read(buf);
}
aFile.close();

buf.flip()通话。首先你读入缓冲区。然后你翻转它,然后再把它读出来。

Java NIO缓冲区

与NIO通道交互时,使用Java NIO缓冲区。数据从通道读入缓冲区,并从缓冲区写入通道。

缓冲区本质上是一个可以写入数据的内存块,然后可以再次读取。该内存块被包装在一个NIO缓冲区对象中,它提供了一组方法,使其更容易使用内存块。

基本缓冲区使用

使用a Buffer读取和写入数据通常遵循这四骤:

  1. 将数据写入缓冲区
  2. 调用 buffer.flip()
  3. 将数据从缓冲区读出
  4. 调用 buffer.clear()buffer.compact()

当数据写入缓冲区时,缓冲区就会对数据的写入量进行跟踪。一旦需要读取数据,您需要使用flip()方法调用将缓冲区从写入模式切换到读取模式。在读取模式下,缓冲区可以读取写入缓冲区的所有数据。

当你读完所有的数据时,你需要清除缓冲区,使其为再次写入做准备。你可以通过两种方法来清楚数据:通过调用clear() compact()方法clear()方法清除整个缓冲区。compact() 方法仅清除您已经读取的数据。任何未读的数据都被移动到缓冲区的开头,数据将在未读数据之后被写入缓冲区。

这是一个简单的Buffer用法示例,用粗体字写入,翻转,读取和清除操作:

RandomAccessFile aFile = new RandomAccessFile(“data / nio-data.txt”,“rw”);
FileChannel inChannel = aFile.getChannel(); //创建容量为48字节的缓冲区
ByteBuffer buf = ByteBuffer.allocate(48); int bytesRead = inChannel.read(buf); //读入缓冲区
while(bytesRead!= -1){ buf.flip(); //使缓冲区准备好读取 而(buf.hasRemaining()){
System.out.print((char)buf.get()); //一次读取1个字节
} buf.clear(); // make buffer ready for writing
bytesRead = inChannel.read(buf);
}
aFile.close();

  缓冲区的容量、位置、和限制

  缓冲区有三个重要属性:

  • 容量
  • 位置
  • 限制

  位置限制的含义取决于缓冲区的是读模式还是写的模式。不管是缓冲区是模式,容量含义是相同的。

  以下是对写入和读取模式的容量,位置和限制的说明。

写入和读取模式下的缓冲区容量,位置和限制。

  容量

  缓冲区具有一定的大小,也称为其“容量”。您只能将capacity字节,长整型,字符等写入缓冲区。如果缓冲区已满,您需要清空写入的数据(读取数据或清除它),然后再写入数据。

  位置

  当你想缓冲区写入数据时,你在某个位置上这样做。最初的位置为0。当一个字节,长整型等已经被写入Buffer,位置被提前指向缓冲区中的下一个单元格以便插入数据。位置可以最大程度地成为 capacity - 1

  当你从缓存中读取数据时,你也可以从一个给定的位置开始读取。当你改变缓冲区模式从写入模式到读取模式时,位置是从你所读数据的位置重置回。类似于缓冲区读取数据这样Bufferposition 前进到下一个位置进行阅读。

  限制

  在写入模式下,缓冲区的限制是可以写入缓冲区的数据量的限制,限制等于该缓冲区的容量

  在缓冲区的读取模式下,限制是可以从数据中读取多少数据的限制。因此,当Buffer转换到读取模式时,将限制设置为写入模式的写入位置。换句话说,您可以读取与写入一样多的字节(限制设置为写入的字节数,以位置标记)。

缓冲区类型

  Java NIO缓冲区类型如下:

  • ByteBuffer
  • MappedByteBuffer
  • CharBuffer
  • DoubleBuffer
  • FloatBuffer
  • IntBuffer
  • LongBuffer
  • ShortBuffer

  您可以看到,这些Buffer类型表示不同的数据类型。也就是,它们可以处理缓冲区中的字节为char,short,int,long,float或double。

  这MappedByteBuffer有点特别。

分配缓冲区

要获取Buffer对象,您必须先分配它。每个Buffer类都有一个allocate()的分配方法。这是一个ByteBuffer分配实例, ByteBuffer容量为48个字节:

ByteBuffer buf = ByteBuffer.allocate(48);

这是一个CharBuffer为1024个字符分配示例:

CharBuffer buf = CharBuffer.allocate(1024);

将数据写入缓冲区

  您可以通过两种方式将数据写入缓冲区:

    1. 将数据从Channel写入Buffer
    2. 通过缓冲区的put()方法自己写入数据。

  以下是一个示例,显示如何Channel将数据写入Buffer

int bytesRead = inChannel.read(buf); //读入缓冲区

这是一个Buffer通过该put()方法将数据写入到数据的示例:

buf.put(127);

  put()方法允许以许多不同的方式写入数据到缓冲区。例如,在特定位置写入,或者将一个字节数组写入缓冲区等等。

flip()   模式切换

  flip()方法可以切换缓冲区的写入模式到读取模式。调用flip()position返回设置为0,并将其设置limit 为刚刚的位置。

  position现在标记了读取位置,并limit标记了被写入缓冲区多少字节,字符等等(也就是可以读取多少字节,字符等的限制)。

从缓冲区读取数据

  从缓冲区读取数据的两种方式。

  1. 将数据从缓冲区读入通道。
  2. 从缓冲区中读取数据,使用其中的一个get()。

  以下是一个示例,说明如何将数据从缓冲区读取到通道中:

//从缓冲区读入通道。
int bytesWritten = inChannel.write(buf);

  以下是Buffer使用get()方法读取数据的示例:

byte aByte = buf.get();    

  get()方法允许从Buffer以许多不同的方式读取数据 。例如,在特定位置读取,或从缓冲区读取字节数组。

byte aByte = buf.get();    

rewind()

  缓冲区的rewind()方法,将positio返回设置为0,因此您可以重新读取缓冲区中的所有数据。在限制保持不变,因此仍然标记多少个元素(字节,字符等),可以从缓冲区被读取。

clear()和compact()

  一旦你完成阅读数据之后,你必须设置Buffer为下一次写入做准备。你可以通过打调用clear()或调用compact()来完成上述操作

  如果调用clear()position是重新设置返回为0,limit设置成容量。或者说是,缓冲区被清除,缓冲区的数据未被清除。只有标记从哪里可以将数据写入缓冲区

  如果Buffer您在调用clear()该数据时有未读的数据将被“忘记”,这意味着您不再有任何标记可以告诉您读取了哪些数据,还那些没有被读取。

  如果还有未读的数据Buffer,并且您想稍后阅读,但您需要先写一些写,调用compact()而不是调用clear()

  compact()将所有未读取的数据复制到开头Buffer。然后它设置position在最后一个未读元素之后。限制大小仍然设置容量,就像clear()。现在Buffer已经为做好准备,但是不会覆盖未读的数据。

mark()和reset()

  可以通过调用缓冲区的mark()方法来标记给定的位置。然后,您可以稍后通过调用该缓冲区的reset() 方法将位置重置回标记的位置。这是一个例子:

buffer.mark();
//调用buffer.get()几次,例如在解析过程中。

buffer.reset(); //将位置设置为标记。 

equals()和compareTo()

  可以使用equals()和compareTo()比较两个缓冲区。

equals()

  两个缓冲区相等的条件:

    A.它们是相同类型(byte,char,int等)

    B.它们在缓冲区中具有相同数量的剩余字节,字符等。

    C.所有剩余的字节,字符等等。

  综上所述,equals只比较缓冲区其中的一部分,而不是每个元素。其实,它只是比较缓冲区的剩余元素。

compareTo()

  compareTo()方法比较两个缓冲区的其余元素(字节,字符等),以便在例如排序线程中使用。

  缓冲区相比其他缓冲区,“小”的条件:

    A.与其他缓冲区中的相应元素相等的第一个元素小于另一个缓冲区中的元素。

    B.所有元素是相等的,但是第一个缓冲区在第二个缓冲区之前用完了元素(它具有较少的元素)。

JAVA NIO学习笔记二 频道和缓冲区的更多相关文章

  1. Java NIO 学习笔记(二)----聚集和分散,通道到通道

    目录: Java NIO 学习笔记(一)----概述,Channel/Buffer Java NIO 学习笔记(二)----聚集和分散,通道到通道 Java NIO 学习笔记(三)----Select ...

  2. Java NIO 学习笔记(三)----Selector

    目录: Java NIO 学习笔记(一)----概述,Channel/Buffer Java NIO 学习笔记(二)----聚集和分散,通道到通道 Java NIO 学习笔记(三)----Select ...

  3. Java NIO 学习笔记(一)----概述,Channel/Buffer

    目录: Java NIO 学习笔记(一)----概述,Channel/Buffer Java NIO 学习笔记(二)----聚集和分散,通道到通道 Java NIO 学习笔记(三)----Select ...

  4. Java NIO 学习笔记(七)----NIO/IO 的对比和总结

    目录: Java NIO 学习笔记(一)----概述,Channel/Buffer Java NIO 学习笔记(二)----聚集和分散,通道到通道 Java NIO 学习笔记(三)----Select ...

  5. Java NIO 学习笔记(五)----路径、文件和管道 Path/Files/Pipe

    目录: Java NIO 学习笔记(一)----概述,Channel/Buffer Java NIO 学习笔记(二)----聚集和分散,通道到通道 Java NIO 学习笔记(三)----Select ...

  6. Java NIO 学习笔记(四)----文件通道和网络通道

    目录: Java NIO 学习笔记(一)----概述,Channel/Buffer Java NIO 学习笔记(二)----聚集和分散,通道到通道 Java NIO 学习笔记(三)----Select ...

  7. Java IO学习笔记二:DirectByteBuffer与HeapByteBuffer

    作者:Grey 原文地址:Java IO学习笔记二:DirectByteBuffer与HeapByteBuffer ByteBuffer.allocate()与ByteBuffer.allocateD ...

  8. Java IO学习笔记二

    Java IO学习笔记二 流的概念 在程序中所有的数据都是以流的方式进行传输或保存的,程序需要数据的时候要使用输入流读取数据,而当程序需要将一些数据保存起来的时候,就要使用输出流完成. 程序中的输入输 ...

  9. Java NIO学习笔记

    Java NIO学习笔记 一 基本概念 IO 是主存和外部设备 ( 硬盘.终端和网络等 ) 拷贝数据的过程. IO 是操作系统的底层功能实现,底层通过 I/O 指令进行完成. 所有语言运行时系统提供执 ...

随机推荐

  1. 访问mapper方法提示invalid bound statement (not found)原因总结

    1.访问所有的mapper都报此错误,检查 mapper.xml 中的 namespace 2.访问mapper中的部分方法时报此错误,检查xml文件中的id是否和接口中的方法名一致 3.mapper ...

  2. jquery中prop,attr,data的区别

    这两天翻了jq的源码,今天看到了jq关于数据存储的几个方法,遂总结一下,和小伙伴没分享一下,哪里说的不对,还望批评指正~~~ 废话不多说,直接上代码: $(function(){ $('#div1') ...

  3. linux bash环境变量简单总结

    来源链接:http://www.178linux.com/8005 原创文章,如有转载,请注明原文地址 一.环境变量简介 Linux是一个多用户的操作系统.每个用户登录系统后,都会有一个专用的运行环境 ...

  4. Http协议与TCP协议

    背景 在日常工作中,经常会遇到某某框架是基于Http协议或者TCP协议,今天,就针对于该协议,整理下 从本质上来说,Http协议与TCP协议是应用在不同网络层,Http协议处于应用层,TCP处于传输层 ...

  5. (二)AppScan使用教程

    1.新建扫描:一般选择 常规扫描 2.选择扫描的平台:web或app 3.扫描配置向导 ①配置URL和服务器 ②配置登录管理 在扫描的过程中,可能会不小心碰到退出按钮导致Appscan注销.因此,要登 ...

  6. C# 之 .net core -- MVC模式的显示、增、删、改

    上一篇介绍数据的创建连接,接下来就是基本的增删改 一.右键添加.控制器 二.选择这个带试图的 三.其他的不要动,点击添加 四.执行一下,改下url 试一下他的增删改. 其实自己写的话可以用form表单 ...

  7. python_网络编程hmac模块验证客户端的合法性

    hmac模块: 比较两个函数的密钥是否一致: import hmac import os msg = os.urandom(32) #生成32位随机字节码 def wdc(): key = b'wdc ...

  8. 关于webpack require.context() 的那点事

    先说 webpack里面有这么一招:使用require.context()方法来自动导入模块 官方文档有点深奥,老衲百度下拿了一段来直接使用,但是想看下它是如何运行的 本篇这里不会有太深入的研究,只是 ...

  9. swoole,http\server 跨域---记一次php网站跨域访问上机实验

    缘由:为了更好的体验swoole组件优良的协程Mysql客户端,实现更好的并发设计:写了一个小程序. 环境准备: 没有采用任何框架,只是使用了smarty模版,来渲染后端php响应的数据,在一个htm ...

  10. CF #589 (Div. 2)C. Primes and Multiplication 快速幂+质因数

    题目链接:https://www.luogu.org/problem/CF1228C 问题可以转化为:求质数 $p$ 在 $1\sim n$ 中的每个数中的次幂之和. 因为 $p$ 是一个质数,只能由 ...