展开
拓展 关闭
订阅号推广码
GitHub
视频
公告栏 关闭

通道(Channel)

  • 简介
1) NIO的通道类似于流,但有些区别如下:
• 通道可以同时进行读写,而流只能读或者只能写
• 通道可以实现异步读写数据
• 通道可以从缓冲读数据,也可以写数据到缓冲

2) BIO 中的 stream 是单向的,例如 FileInputStream 对象只能进行读取数据的操作,而 NIO 中的通道(Channel)是双向的,可以读操作,也可以写操作。
3) Channel在NIO中是一个接口public interface Channel extends Closeable{}
4) 常用的 Channel 类有:FileChannel、DatagramChannel、ServerSocketChannel 和SocketChannel。【ServerSocketChanne 类似ServerSocket , SocketChannel 类似 Socket】
5) FileChannel 用于文件的数据读写,DatagramChannel 用于 UDP 的数据读写,ServerSocketChannel 和 SocketChannel 用于 TCP的数据读写。
  • FileChannel 类
FileChannel主要用来对本地文件进行 IO 操作,常见的方法有
1) public int read(ByteBuffer dst) ,从通道读取数据并放到缓冲区中
2) public int write(ByteBuffer src) ,把缓冲区的数据写到通道中
3) public long transferFrom(ReadableByteChannel src, long position, long count),从目标通道中复制数据到当前通道
4) public long transferTo(long position, long count, WritableByteChannel target),把数据从当前通道复制给目标通道
  • 案例1
1) 使用前面学习后的ByteBuffer(缓冲) 和 FileChannel(通道), 将 "hello,尚硅谷" 写入到file01.txt 中
2) 文件不存在就创建

public class NIOFileChannel01 {
    public static void main(String[] args) throws Exception{
        String str = "hello,尚硅谷";
        //创建一个输出流->channel
        FileOutputStream fileOutputStream = new FileOutputStream("d:\\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
1) 使用前面学习后的ByteBuffer(缓冲) 和 FileChannel(通道), 将 file01.txt 中的数据读入到程序,并显示在控制台屏幕
2) 假定文件已经存在

public class NIOFileChannel02 {
    public static void main(String[] args) throws Exception {

        //创建文件的输入流
        File file = new File("d:\\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();

    }
}
  • 案例3
1) 使用 FileChannel(通道) 和 方法 read , write,完成文件的拷贝
2) 拷贝一个文本文件 1.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 final Buffer clear() {
                position = 0;
                limit = capacity;
                mark = -1;
                return this;
            }
             */
            byteBuffer.clear(); //清空buffer
            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
1) 使用 FileChannel(通道) 和 方法 transferFrom ,完成文件的拷贝
2) 拷贝一张图片

public class NIOFileChannel04 {
    public static void main(String[] args)  throws Exception {

        //创建相关流
        FileInputStream fileInputStream = new FileInputStream("d:\\a.jpg");
        FileOutputStream fileOutputStream = new FileOutputStream("d:\\a2.jpg");

        //获取各个流对应的filechannel
        FileChannel sourceCh = fileInputStream.getChannel();
        FileChannel destCh = fileOutputStream.getChannel();

        //使用transferForm完成拷贝
        destCh.transferFrom(sourceCh,0,sourceCh.size());
        //关闭相关通道和流
        sourceCh.close();
        destCh.close();
        fileInputStream.close();
        fileOutputStream.close();
    }
}
posted @ 2022-08-04 15:23  DogLeftover  阅读(161)  评论(0编辑  收藏  举报