通道(Channel)的原理获取
通道表示打开到 IO 设备(例如:文件、套接字)的连接。若需要使用 NIO 系统,需要获取用于连接 IO 设备的通道以及用于容纳数据的缓冲区。然后操作缓冲区,对数据进行处理。Channel 负责传输, Buffer 负责存储。通道是由 java.nio.channels 包定义的。 Channel 表示 IO 源与目标打开的连接。Channel 类似于传统的“流”。只不过 Channel本身不能直接访问数据, Channel 只能与Buffer 进行交互。
java.nio.channels.Channel 接口:
|--FileChannel 本地文件的通道
|--SocketChannel
|--ServerSocketChannel
|--DatagramChannel
网络的关于通道
获取通道
1. Java 针对支持通道的类提供了 getChannel() 方法
本地 IO:
FileInputStream/FileOutputStream
RandomAccessFile
网络IO:
Socket
ServerSocket
DatagramSocket
2. 在 JDK 1.7 中的 NIO.2 针对各个通道提供了静态方法 open()
3. 在 JDK 1.7 中的 NIO.2 的 Files 工具类的 newByteChannel()
package com.toov5.Nio;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import org.junit.jupiter.api.Test;
public class BUfferTest02 {
// 非直接缓冲区 读写操作
@Test
public void BUfferTest() throws IOException {
// 读入流
FileInputStream fileInputStream = new FileInputStream("aa.jpg");
// 写入流
FileOutputStream fileOutputStream = new FileOutputStream("bb.jpg");
// 创建通道
FileChannel iChannel = fileInputStream.getChannel(); // 读入流的通道
FileChannel oChannel = fileOutputStream.getChannel(); // 写入流的通道
//分配制定缓冲区大小
ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
while (iChannel.read(byteBuffer) != -1) {
//开启读取模式
byteBuffer.flip();
//将数据写入到通道中
oChannel.write(byteBuffer);
byteBuffer.clear();
}
//关闭通道、关闭连接
iChannel.close();
oChannel.close();
fileInputStream.close();
fileOutputStream.close();
}
}
运行结果:
直接缓冲区:
package com.toov5.Nio;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.FileChannel.MapMode;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import org.junit.jupiter.api.Test;
public class BUfferTest02 {
@Test
public void testZhiJie() throws IOException {
//创建管道
FileChannel inChannel =FileChannel.open(Paths.get("aa.jpg"), StandardOpenOption.READ);
FileChannel outChannel =FileChannel.open(Paths.get("bb.jpg"),StandardOpenOption.READ,StandardOpenOption.WRITE,StandardOpenOption.CREATE );
//定义映射文件
MappedByteBuffer inMappedByteBuffer =inChannel.map(MapMode.READ_ONLY, 0, inChannel.size());
MappedByteBuffer outMappedByteBuffer =outChannel.map(MapMode.READ_WRITE, 0, inChannel.size());
//直接对缓冲区操作
byte[] bytes = new byte[inMappedByteBuffer.limit()];
inMappedByteBuffer.get(bytes);
outMappedByteBuffer.put(bytes);
inChannel.close();
outChannel.close();
System.out.println("操作直接缓冲区完毕");
}
// 非直接缓冲区 读写操作
@Test
public void BUfferTest() throws IOException {
// 读入流
FileInputStream fileInputStream = new FileInputStream("aa.jpg");
// 写入流
FileOutputStream fileOutputStream = new FileOutputStream("bb.jpg");
// 创建通道
FileChannel iChannel = fileInputStream.getChannel(); // 读入流的通道
FileChannel oChannel = fileOutputStream.getChannel(); // 写入流的通道
//分配制定缓冲区大小
ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
while (iChannel.read(byteBuffer) != -1) {
//开启读取模式
byteBuffer.flip();
//将数据写入到通道中
oChannel.write(byteBuffer);
byteBuffer.clear();
}
//关闭通道、关闭连接
iChannel.close();
oChannel.close();
fileInputStream.close();
fileOutputStream.close();
}
}