NIO学习笔记(1)-Buffer,Channel

简介:

 Buffer 是一个对象, 它包含一些要写入或者刚读出的数据。 在 NIO 中加入 Buffer 对象,体现了新库与原 I/O 的一个重要区别。在面向流的 I/O 中,您将数据直接写入或者将数据直接读到 Stream 对象中。

 

在 NIO 库中,所有数据都是用缓冲区处理的。在读取数据时,它是直接读到缓冲区中的。在写入数据时,它是写入到缓冲区中的。任何时候访问 NIO 中的数据,您都是将它放到缓冲区中.

 

Channel是一个对象,可以通过它读取和写入数据。拿 NIO 与原来的 I/O 做个比较,通道就像是流。

 

正如前面提到的,所有数据都通过 Buffer 对象来处理。您永远不会将字节直接写入通道中,相反,您是将数据写入包含一个或者多个字节的缓冲区。同样,您不会直接从通道中读取字节,而是将数据从通道读入缓冲区,再从缓冲区获取这个字节。

 

 flip:

 

现在我们要将数据写到输出通道中。在这之前,我们必须调用 flip() 方法。这个方法做两件非常重要的事:

 

它将 limit 设置为当前 position。

它将 position 设置为 0。

 

拷贝文件的一个例子

 
  1. public static void copy() throws IOException 
  2.     { 
  3.         FileInputStream fin = new FileInputStream("e:/main.rar"); 
  4.         FileChannel finc = fin.getChannel(); 
  5.         ByteBuffer buf = ByteBuffer.allocate(8); 
  6.          
  7.         FileOutputStream fout = new FileOutputStream("e:/back.rar"); 
  8.         FileChannel foutc = fout.getChannel(); 
  9.         int readNum = 0
  10.          
  11.         buf.clear(); 
  12.      
  13.         while(readNum != -1){//读完时返回-1 
  14.             readNum = finc.read(buf); 
  15.             buf.flip();//将缓存字节数组的指针设置为数组的开始序列即数组下标0。这样就可以从buffer开头,对该buffer进行遍历(读取)了。 
  16.             foutc.write(buf); 
  17.             buf.clear(); 
  18.         } 
  19.  
  20.         finc.close(); 
  21.         fin.close(); 
  22.         fout.close(); 
  23.         foutc.close(); 
  24.     } 

 

分散/聚集 I/O 是使用多个而不是单个缓冲区来保存数据的读写方法。

 

通道可以有选择地实现两个新的接口: ScatteringByteChannel 和 GatheringByteChannel。一个 ScatteringByteChannel 是一个具有两个附加读方法的通道:

long read( ByteBuffer[] dsts );

long read( ByteBuffer[] dsts, int offset, int length );

例如

fin.getChannel().read(dsts);

在 分散读取 中,通道依次填充每个缓冲区。填满一个缓冲区后,它就开始填充下一个。在某种意义上,缓冲区数组就像一个大缓冲区。

分散/聚集的应用

分散/聚集 I/O 对于将数据划分为几个部分很有用。例如,您可能在编写一个使用消息对象的网络应用程序,每一个消息被划分为固定长度的头部和固定长度的正文。您可以创建一个刚好可以容纳头部的缓冲区和另一个刚好可以容难正文的缓冲区。当您将它们放入一个数组中并使用分散读取来向它们读入消息时,头部和正文将整齐地划分到这两个缓冲区中。

我们从缓冲区所得到的方便性对于缓冲区数组同样有效。因为每一个缓冲区都跟踪自己还可以接受多少数据,所以分散读取会自动找到有空间接受数据的第一个缓冲区。在这个缓冲区填满后,它就会移动到下一个缓冲区。

 

聚集写入 类似于分散读取,只不过是用来写入。它也有接受缓冲区数组的方法:

long write( ByteBuffer[] srcs );

long write( ByteBuffer[] srcs, int offset, int length );

聚集写对于把一组单独的缓冲区中组成单个数据流很有用。为了与上面的消息例子保持一致,您可以使用聚集写入来自动将网络消息的各个部分组装为单个数据流,以便跨越网络传输消息。

 

 本文转自 dogegg250 51CTO博客,原文链接:http://blog.51cto.com/jianshusoft/692331,如需转载请自行联系原作者

相关文章
|
4月前
|
存储 编解码 移动开发
技术笔记:NIO流—理解Buffer、Channel概念和NIO的读写操作
技术笔记:NIO流—理解Buffer、Channel概念和NIO的读写操作
32 1
|
8天前
|
Java
让星星⭐月亮告诉你,Java NIO之Buffer详解 属性capacity/position/limit/mark 方法put(X)/get()/flip()/compact()/clear()
这段代码演示了Java NIO中`ByteBuffer`的基本操作,包括分配、写入、翻转、读取、压缩和清空缓冲区。通过示例展示了`position`、`limit`和`mark`属性的变化过程,帮助理解缓冲区的工作原理。
17 2
|
5月前
|
Java 索引
📌 Java NIO Buffer
Java NIO缓冲区在与NIO通道交互时使用。数据从通道读取到缓冲区,然后从缓冲区写入通道。 缓冲区本质上是一块内存,可以在其中写入数据,然后再进行读取。这个内存块被封装在一个NIOBuffer对象中,该对象提供了一组方法,可以更容易地使用内存块。
|
5月前
|
缓存 网络协议 Java
📌 Java NIO Channel
Java NIOChannel和传统的流相似,但是也存在一些差异: • 在同一个Channel通道中,既可以进行 读操作 也可以进行 写操作,但是 流 只能进行 读 或者 写 其中一种操作。 • Channel通道可以进行异步读写。 • Channel可以从 Buffer中进行读写操作。将数据从Channel通道读取到Buffer缓冲区,并将数据从Buffer缓冲区写入Channel通道。
|
存储 网络协议 Java
Netty入门到超神系列-Java NIO 三大核心(selector,channel,buffer)
选择器,也叫多路复用器,Java的NIO通过selector实现一个线程处理多个客户端链接,多个channel可以注册到同一个Selector,Selector能够监测到channel上是否有读/写事件发生,从而获取事件和对事件进行处理,所以Selector切到哪个channel是由事件决定的。当线程从某个客户端通道未读取到数据时,可以把空闲时间用来做其他任务,性能得到了提升。
152 0
|
弹性计算 Java API
Netty入门到超神系列-Java NIO 三大核心(selector,channel,buffer)
理解Selector 和 Channel Selector 选择器,也叫多路复用器,可以同时处理多个客户端连接,多路复用器采用轮询机制来选择有读写事件的客户端链接进行处理。 通过 Selector ,一个 I/O 线程可以并发处理 N 个客户端连接和读写操作,这解决了传统同步阻塞 I/O 一连接一线程模型,架构的性能、弹性伸缩能力和可靠性都得到了极大的提升。 由于它的读写操作都是非阻塞的,这就可以充分提升 IO 线程的运行效率,避免由于频繁 I/O 阻塞导致的线程挂起。
244 0
|
存储 Java
NIO之Buffer解读(下)
NIO之Buffer解读(下)
|
存储 Java 容器
|
缓存 Java
JAVA NIO学习笔记一
JAVA NIO学习笔记一
57 0
|
缓存 网络协议 Java
Java NIO学习(二):Channel通道
Java NIO 的通道类似流,但又有些不同:
165 0
Java NIO学习(二):Channel通道