Java NIO - Kuangcp/Note GitHub Wiki
目录 start
-
NIO
- Java IO 与 NIO的主要区别
-
通道(Channel)与缓冲区(Buffer)
- [1、缓冲区(Buffer)](#1、[缓冲区buffer]srcbuffertestbufferjava)
-
2、通道
- 1、主要的Channel接口实现类
- 2、使用方法
- 3、通道之间的数据传输
- 4、分散(Scatter)与聚集(Gather)
- [5、字符集](#5、[字符集]srcchanneltestcharsetjava)
- 6、网路IO(核心内容)
- [3、管道](#3、[管道]srcpipetestpipejava)
目录 end|2020-04-27 23:42|
IO | NIO |
---|---|
面向流 | 面向缓冲区 |
阻塞IO | 非阻塞IO |
选择器 |
Channel表示打开IO设备(如,文件、套接字)的连接。若要使用NIO,则需获取用于连接IO设备的管道以及容纳数据的缓冲区。然后操作缓冲区,对数据进行处理
在Java NIO中负责数据的存取,缓冲区就是数组用于操作不同类型的数据。不同的数据类型提供了不同的缓冲区,boolean除外。
- ByteBuffer
- CharBuffer
- DoubleBuffer
- FloatBuffer
- IntBuffer
- LongBuffer
- ShortBuffer
-
使用
allocate()
方法获取一定大小的缓冲区:ByteBuffer buffer = ByteBuffer.allocate(1024);
-
使用
put()
存入数据到缓冲区:buffer.put("hello".getBytes());
-
使用
flip()
切换成读取数据模式:buffer.flip();
-
使用
get()
获取缓冲区内的数据:byte[] bytes = new byte[buffer.limit()]; buffer.get(bytes);
-
mark
:标记, 表示记录当前position的位置,可通过reset()恢复到mark的位置 -
position
:位置,缓冲区中正在操作数据的位置 -
limit
:界限,缓冲区中可以操作数据的大小。 limit后的数据不可读写 -
capacity
:容量,表示缓冲区中最大存储数据的容量,一旦声明不可改变
-
非直接缓冲区:通过
allocate()
方法分配缓冲区,缓冲区将建立在JVM的内存中 -
直接缓冲区:通过
allocateDirect()
方法分配缓冲区,缓冲区将直接建立在物理内存中
Channel表示IO源与目标打开的连接,类似于传统的流。不过Channel不能直接访问数据,Channel只能与Buffer进行交互
- FileChannel
- SocketChannel
- ServerSocketChannel
- DatagramChannel
-
Java针对支持通道的类提供
getChannel()
方法,这些类有:-
本地IO
- FileInputStream/FileOutputStream
- RandomAccessFile
-
网络IO
- Socket
- ServerSocket
- DatagramSocket
-
-
JDK 1.7中的NIO2针对各个通道提供了静态方法
open()
-
JDK 1.7中的NIO2中的Files工具类的
newByteChannel()
方法
- 利用Channel完成文件的复制(非直接缓冲区).
@Test
public void test1() throws IOException {
FileInputStream fis = new FileInputStream("JavaNIO.iml");
FileOutputStream fos = new FileOutputStream("JavaNIO2.iml");
// 获取通道
FileChannel inputChannel = fis.getChannel();
FileChannel outputChannel = fos.getChannel();
// 分配指定大小的缓冲区
ByteBuffer buffer = ByteBuffer.allocate(1024);
// 将通道内的数据读入缓冲区
while (inputChannel.read(buffer) != -1) {
// 将缓冲区内的数据写入通道
buffer.flip(); // 切换为读数据
outputChannel.write(buffer);
buffer.clear(); // 清空缓冲区
}
// 关闭通道
outputChannel.close();
inputChannel.close();
fos.close();
fis.close();
}
- 使用直接缓冲区复制文件(内存映射文件).
@Test
public void test2() throws IOException {
// 使用Open()获取通道
FileChannel inputChannel = FileChannel.open(Paths.get("JavaNIO.iml"), StandardOpenOption.READ);
FileChannel outputChannel = FileChannel.open(Paths.get("JavaNIO2.iml"),
StandardOpenOption.READ, StandardOpenOption.WRITE, StandardOpenOption.CREATE_NEW);
// 内存映射文件,和使用allocateDirect()获取内存一样,内存在物理内存中
MappedByteBuffer inputMappedBuffer = inputChannel.map(FileChannel.MapMode.READ_ONLY, 0, inputChannel.size());
MappedByteBuffer outputMappedBuffer = outputChannel.map(FileChannel.MapMode.READ_WRITE, 0, inputChannel.size());
// 直接对缓冲区进行读写操作
byte[] bytes = new byte[inputMappedBuffer.limit()];
inputMappedBuffer.get(bytes);
outputMappedBuffer.put(bytes);
// 关闭通道
inputChannel.close();
outputChannel.close();
}
-
主要方法
- transferFrom()
- transferTo()
@Test
public void test3() throws IOException {
// 使用Open()获取通道
FileChannel inputChannel = FileChannel.open(Paths.get("JavaNIO.iml"), StandardOpenOption.READ);
FileChannel outputChannel = FileChannel.open(Paths.get("JavaNIO2.iml"),
StandardOpenOption.READ, StandardOpenOption.WRITE, StandardOpenOption.CREATE_NEW);
// 通道间的数据传输(二用一)
// inputChannel.transferTo(0, inputChannel.size(), outputChannel);
outputChannel.transferFrom(inputChannel, 0, inputChannel.size());
inputChannel.close();
outputChannel.close();
}
-
分散读取(Scattering Reads): 将通道中的数据分散到多个缓冲区中
-
聚集写入(Gathering Writes):将多个缓冲区内的数据聚集到通道中
5、字符集
指定字符集,避免乱码。常用于CharBuffer与ByteBuffer之间。
传统IO为阻塞式的,NIO通过选择器实现非阻塞式IO
-
核心内容
- Channel
- Buffer
- Selector
1、TCP连接
主要Channel为SocketChannel与ServerSocketChannel;
2、UDP连接
主要Channel为DatagramChannel
3、管道
Java NIO 管道是2个线程之间的单向数据连接,Pipe有一个source通道和一个sink通道。数据会被写到sink通道,从source通道读取