NIO三个核心组件 ---- Channel(管道)

Channel(管道):

1.类似于流,但是区别如下:

通道可以同时进行读写,流只能读或者写
通道可以实现异步读写数据
通道可以从缓冲区(buffer)读取数据,也可以写数据到缓冲区(buffer)

2.BIO中的stream是单向的,Channel是双向的,可以读操作,也可以写操作
3 Channel在NIO中是一个接口

常用的Channel类有: FileChannel,DatagramChannel,ServerScoketChannel和SocketChannel
FileChannel 用于文件的数据读写,DatagramChannel用于UDP的数据读写,ServerScoketChannel和SocketChannel用于TCP的数据读写

NIO的网络通讯流程

在服务器端会创建一个ServerScoketChannel(ServerScoketChannelImpl),在对应产生的客户端生成一个SocketChannel(SocketChannelImpl)

Channel的主要方法:

1.read: 从通道中读取数据,并放到缓冲区中
2.write : 把缓冲区数据写到通道里
3.transferFrom :从目标通道中复制数据到当前通道
4.transferTo : 把数据从当前通道复制给目标通道
下面写一个Channel对文件读写的操作:
在文件里写

package com.jym.nio;

import java.io.FileOutputStream;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;

/**
 * @program: JymNetty
 * @description: Channel学习
 * @author: jym
 * @create: 2020/02/01
 */
public class JymFileChannel {
    public static void main(String[] args) throws Exception {
        String str = "hello,jym";
        FileOutputStream fileOutputStream = new FileOutputStream("D:\\jym.txt");
        // 通过fileOutputStream获取对应的channel,真实类型为FileChannelImpl
        FileChannel fileChannel = fileOutputStream.getChannel();
        // 创建一个缓冲区
        ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
        // 将str放入到byteBuffer
        byteBuffer.put(str.getBytes());
        // 将byteBuffer进行翻转,因为需要读
        byteBuffer.flip();
        // 将byteBuffer数据写入到fileChannel
        fileChannel.write(byteBuffer);
        fileOutputStream.close();
    }
}

从文件里读取内容:

package com.jym.nio;

import java.io.File;
import java.io.FileInputStream;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;

/**
 * @program: JymNetty
 * @description: 读取数据
 * @author: jym
 * @create: 2020/02/01
 */
public class JymFileChannel1 {
    public static void main(String[] args) throws Exception {
        File file = new File("D:\\jym.txt");
        FileInputStream fileInputStream = new FileInputStream(file);
        // 通过fileInputStream 获取channel,实际类型为FileChannelImpl
        FileChannel fileInputStreamChannel = fileInputStream.getChannel();

        ByteBuffer byteBuffer = ByteBuffer.allocate((int)file.length());
        // 将通道数据读入到缓冲区中
        fileInputStreamChannel.read(byteBuffer);
        // 将字节信息转成字符串
        System.out.println(new String(byteBuffer.array()));
        fileInputStream.close();
    }
}

让我们整合一下,完成一个文件的拷贝

package com.jym.nio;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;

/**
 * @program: JymNetty
 * @description: 文件拷贝练习
 * @author: jym
 * @create: 2020/02/01
 */
public class JymFileChannel2 {
    public static void main(String[] args) throws Exception {
        File file = new File("D:\\壁纸\\1.jpg");
        FileInputStream fileInputStream = new FileInputStream(file);
        // 通过fileInputStream 获取channel,实际类型为FileChannelImpl
        FileChannel fileInputStreamChannel = fileInputStream.getChannel();

        FileOutputStream fileOutputStream = new FileOutputStream("3.jpg");
        // 通过fileOutputStream获取对应的channel,真实类型为FileChannelImpl
        FileChannel fileOutputStreamChannel = fileOutputStream.getChannel();


        ByteBuffer byteBuffer = ByteBuffer.allocate(512);
        while (true){
            byteBuffer.clear();
            // 将通道数据读入到缓冲区中
            int read = fileInputStreamChannel.read(byteBuffer);
            if(read == -1){
                break;
            }
            // 需要写,所以得切换
            byteBuffer.flip();
            // 将byteBuffer数据写入到fileChannel
            fileOutputStreamChannel.write(byteBuffer);
        }

        fileInputStream.close();
        fileOutputStream.close();
    }
}

注意:在循环里读取数据的时候,需要clean()一下,如果不clean,它读取的一直为0,进入死循环
用transfer的方法来进行文件的拷贝,这个流程就简单不少:

package com.jym.nio;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.nio.channels.FileChannel;

/**
 * @program: JymNetty
 * @description: transfer测试
 * @author: jym
 * @create: 2020/02/01
 */
public class JymFileChannel3 {
    public static void main(String[] args) throws Exception {
        File file = new File("D:\\壁纸\\1.jpg");
        FileInputStream fileInputStream = new FileInputStream(file);
        FileChannel fileInputStreamChannel = fileInputStream.getChannel();

        FileOutputStream fileOutputStream = new FileOutputStream("4.jpg");
        FileChannel fileOutputStreamChannel = fileOutputStream.getChannel();

        fileOutputStreamChannel.transferFrom(fileInputStreamChannel,0,fileInputStreamChannel.size());

        fileInputStreamChannel.close();
        fileOutputStreamChannel.close();
        fileInputStream.close();
        fileOutputStream.close();
    }
}

学习年限不足,知识过浅,说的不对请见谅。

世界上有10种人,一种是懂二进制的,一种是不懂二进制的。

发布了71 篇原创文章 · 获赞 54 · 访问量 42万+

猜你喜欢

转载自blog.csdn.net/weixin_43326401/article/details/104138779