通道(Channel)基本介绍
- NIO 的通道类似于流,但有些区别:
- 通道可以同时进行读写,而流只能读或者只能写
- 通道可以实现异步读写数据
- 通道可以从缓冲读数据,也可以写数据到缓冲
- BIO中的stream是单向的,例如FileInputStream对象只能进行读取数据的操作,而NIO中的通道(Channel)是双向的,可以读操作,也可以写操作
- Channel在NIO中是一个接口
public interface Channel extends Closeable{} - 常见的Channel类有:FileChannel、DatagramChannel、ServerSocketChannel和SocketChannel
- FileChannel用于文件的数据读写
DatagramChannel用于UDP的数据读写
ServerSocketChannel和SocketChannel用于TCP的数据读写
FileChannel类
FileChannel主要用来对本地文件进行IO操作,常见的方法有
- public abstract int read(ByteBuffer dst) ,从通道读取数据并放到缓冲区重
- public abstract int write(ByteBuffer src),把缓冲区的数据写到通道中
- public abstract long transferFrom(ReadableByteChannel src, long position, long count),从目标通道中复制数据到当前通道
- public abstract long transferTo(long position, long count,WritableByteChannel target),把数据从当前通道复制给目标通道
应用实例1-本地文件写数据
使用前面学到的ByteBuffer(缓冲)和(通道),将字符串写入file01.txt中
package com.example.demo.netty;
import java.io.FileOutputStream;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
/**
* 应用实例1-本地文件写数据
* 使用前面学到的ByteBuffer(缓冲)和(通道),将字符串写入file01.txt中
*/
public class NioFileChannel01 {
public static void main(String[] args) throws Exception {
String str = "hello 世界";
// 创建一个输出流 --> channel
FileOutputStream fos = new FileOutputStream("D:/file01.txt");
// 通过FileOutputStream 获取 对应的channel
// 这个fileChannel 真实的类型是 FileChannelImpl
FileChannel fileChannel = fos.getChannel();
// 创建一个缓冲区
ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
// 将str放入缓冲区
byteBuffer.put(str.getBytes());
// 对byteBuffer进行反转
byteBuffer.flip();
// 将缓冲区数据写入fileChannel
fileChannel.write(byteBuffer);
fos.close();
}
}
应用实例2-本地文件读数据
使用前面学到的ByteBuffer(缓冲)和(通道),将file01.txt中的数据读入到程序,并显示在控制台屏幕
package com.example.demo.netty;
import java.io.FileInputStream;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
/**
* 应用实例2-本地文件读数据
* 使用前面学到的ByteBuffer(缓冲)和(通道),将file01.txt中的数据读入到程序,并显示在控制台屏幕
*/
public class NioFileChannel02 {
public static void main(String[] args) throws Exception {
// 创建文件的输入流
FileInputStream fis = new FileInputStream("D:/file01.txt");
// 通过FileInputStream 获取对应的 FileChannel -> 实际类型 FileChannelImpl
FileChannel fileChannel = fis.getChannel();
// 创建缓冲区
ByteBuffer byteBuffer = ByteBuffer.allocate((int) fileChannel.size());
// 将通道的数据读取到buffer
fileChannel.read(byteBuffer);
// 将byteBuffer的 字节数据 转换成 string
System.out.println(new String(byteBuffer.array()));
fis.close();
}
}
应用实例3-使用一个Buffer完成文件的读取
使用FileChannel(通道)和方法read write,完成文件的拷贝
package com.example.demo.netty;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
/**
* 应用实例3-使用一个Buffer完成文件读取
* 使用FileChannel(通道)和方法read write,完成文件的拷贝
*/
public class NioFileChannel03 {
public static void main(String[] args) throws Exception {
FileInputStream fileInputStream = new FileInputStream("1.txt");
FileChannel fileChannel01 = fileInputStream.getChannel();
FileOutputStream fileOutputStream = new FileOutputStream("2.txt");
FileChannel fileChannel02 = fileOutputStream.getChannel();
ByteBuffer byteBuffer = ByteBuffer.allocate(512);
//循环读取
while (true) {
//一定不要忘了复位
byteBuffer.clear();
int read = fileChannel01.read(byteBuffer);
if (read == -1) {//表示读完
break;
}
//将buffer中的数据写入到fileChannel02 -> 2.txt
byteBuffer.flip();
fileChannel02.write(byteBuffer);
}
}
}
应用实例4-拷贝文件
使用FileChannel(通道)和方法transferFrom,完成文件的拷贝
package com.example.demo.netty;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.nio.channels.FileChannel;
/**
* 应用实例4-拷贝文件transferFrom方法
* 使用FileChannel(通道)和方法transferFrom,完成文件的拷贝
*/
public class NioFileChannel04 {
public static void main(String[] args) throws Exception {
//创建相关流
FileInputStream fileInputStream = new FileInputStream("a.png");
FileOutputStream fileOutputStream = new FileOutputStream("b.png");
//获取各个流对应的fileChannel
FileChannel sourceCh = fileInputStream.getChannel();
FileChannel destCh = fileOutputStream.getChannel();
//使用transferFrom完成拷贝
destCh.transferFrom(sourceCh, 0, sourceCh.size());
//关闭相关通道和流
sourceCh.close();
destCh.close();
fileInputStream.close();
fileOutputStream.close();
}
}