文章目录
- 一、Channel 基本介绍
- 二、FileChannel 类
- 三、Channel 应用案例
- 1. 应用实例 1 - 本地文件写数据
- 2. 应用实例 2 - 本地文件读数据
- 3. 应用实例 3 - 使用一个Buffer 完成文件读取、写入
- 4. 应用实例 4 - 拷贝文件transferFrom方法
 
一、Channel 基本介绍
- NIO的通道类似于流,但有些区别如下:
通道可以同时进行读写,而流只能读或者只能写;
通道可以实现异步读写数据;
通道可以从缓冲区读数据,也可以写数据到缓冲区;
- BIO 中的 stream 是单向的,例如 FileInputStream 对象只能进行读取数据的操作,而 NIO 中的Channel(通道)是双向的,可以读操作,也可以写操作 ;
- Channel在NIO中是一个接口
public interface Channel extends Closeable{}- 常用的 Channel 类有:FileChannel、DatagramChannel、ServerSocketChannel 和 SocketChannel;【ServerSocketChanne 类似 ServerSocket , SocketChannel 类似 Socket】
- FileChannel 用于文件的数据读写,DatagramChannel 用于 UDP 的数据读写,ServerSocketChannel 和 SocketChannel 用于 TCP 的数据读写;
二、FileChannel 类
FileChannel 主要用来对本地文件进行 IO 操作,常见的方法有:
// 站在Buffer角度看,read in 数据到Buffer,从Bufferwrite out Channel
public int read(ByteBuffer dst) //从通道读取数据并放到缓冲区中
public int write(ByteBuffer src) //把缓冲区的数据写到通道中
public long transferFrom(ReadableByteChannel src, long position, long count) //从目标通道中复制数据到当前通道
public long transferTo(long position, long count, WritableByteChannel target) //把数据从当前通道复制给目标通道
三、Channel 应用案例
1. 应用实例 1 - 本地文件写数据
实例要求:
(1)用 ByteBuffer(缓冲) 和 FileChannel(通道), 将 “hello,你好” 写入到 file01.txt 中;
(2)文件不存在就创建;
import java.io.FileOutputStream;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
public class NIOFileChannel01 {
    public static void main(String[] args) throws Exception{
        String str = "hello,你好";
        // 创建一个输出流
        FileOutputStream fileOutputStream = new FileOutputStream("D:\\GitHub\\NettyDemo\\file01.txt");
        // 通过 fileOutputStream 获取对应的 FileChannel
        // 这个 fileChannel 真实类型是 FileChannelImpl
        FileChannel fileChannel = fileOutputStream.getChannel();
        // 创建一个缓冲区 ByteBuffer
        ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
        // 将 str 放入 byteBuffer
        byteBuffer.put(str.getBytes());
        // 对byteBuffer 进行flip
        byteBuffer.flip();
        // 将byteBuffer 数据写到 fileChannel
        fileChannel.write(byteBuffer);
        fileOutputStream.close();
    }
}
2. 应用实例 2 - 本地文件读数据
(1)使用 ByteBuffer(缓冲) 和 FileChannel(通道), 将 file01.txt 中的数据读入到程序,并显示在控制台;
(2)假定文件已经存在;
public class NIOFileChannel02 {
    public static void main(String[] args) throws Exception {
        // 创建文件的输入流
        File file = new File("D:\\GitHub\\NettyDemo\\file01.txt");
        FileInputStream fileInputStream = new FileInputStream(file);
        // 通过fileInputStream 获取对应的FileChannel -> 实际类型  FileChannelImpl
        FileChannel fileChannel = fileInputStream.getChannel();
        // 创建缓冲区
        ByteBuffer byteBuffer = ByteBuffer.allocate((int) file.length());
        // 将通道的数据读入到Buffer
        fileChannel.read(byteBuffer);
        // 将byteBuffer 的字节数据 转成String
        System.out.println(new String(byteBuffer.array()));
        fileInputStream.close();
    }
}
输出:
hello,你好
3. 应用实例 3 - 使用一个Buffer 完成文件读取、写入
实例要求:
(1)使用 FileChannel(通道) 和 方法 read 、 write,完成文件的拷贝;
(2)拷贝一个文本文件 file01.txt , 放在项目下即可;

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) {
            // 这里有一个重要的操作,一定不要忘了
            /*public Buffer clear() { // clear源码
		       position = 0;
		        limit = capacity;
		        mark = -1;
		        return this;
		    }*/
            // 清空buffer
            // 如果不clear,此时position=limit,则read的返回值为0,退不出循环,还会一直重复写
            byteBuffer.clear();
            int read = fileChannel01.read(byteBuffer);
            System.out.println("read = " + read);
            // 表示读完
            if(read == -1) {
                break;
            }
            // 将buffer 中的数据写入到 fileChannel02 -- 2.txt
            byteBuffer.flip();
            fileChannel02.write(byteBuffer);
        }
        // 关闭相关的流
        fileInputStream.close();
        fileOutputStream.close();
    }
}
4. 应用实例 4 - 拷贝文件transferFrom方法
实例要求:
(1)使用 FileChannel(通道) 和 transferFrom方法,完成文件的拷贝;
(2)拷贝一张图片;
public class NIOFileChannel04 {
    public static void main(String[] args)  throws Exception {
        // 创建相关流
        FileInputStream fileInputStream = new FileInputStream("D:\\GitHub\\NettyDemo\\a.png");
        FileOutputStream fileOutputStream = new FileOutputStream("D:\\GitHub\\NettyDemo\\a2.png");
        // 获取各个流对应的fileChannel
        FileChannel sourceChannel = fileInputStream.getChannel();
        FileChannel destChannel = fileOutputStream.getChannel();
        // 使用transferForm完成拷贝
        destChannel.transferFrom(sourceChannel, 0, sourceChannel.size());
        // 关闭相关通道和流
        sourceChannel.close();
        destChannel.close();
        fileInputStream.close();
        fileOutputStream.close();
    }
}














![[ 红队知识库 ] 常见防火墙(WAF)拦截页面](https://img-blog.csdnimg.cn/9a895acff51c4beaa1d36d414afe7470.png)





