(一)Netty从入门到放弃NIO入门

NIO三大组件

  • Buffer 缓冲区

    Nio中的Buffer可以理解为一个数据容器,任何对数据的操作都是在Buffer中进行的。Nio中从Buffer中写入数据到Channel,或者从Channel中读取数据到Buffer。Buffer子类主要有基本类型的几种Buffer其中最常用的是ByteBuffer。

    核心属性

    • capacity: Buffer 的缓冲区大小 一旦声明不可变
    • limit 界限 表示缓冲区操作数据大小 limit 之后的数据不可读写,可以修改
    • position 位置 指针 缓冲区下一个要被操作数据的位置或者指针
    • mark 表示 可以标记当前position的位置

    常用API

    • allocate(size) 创建一个指定大小的Buffer
    • flip() 读写模式切换
    • get() 从Buffer中获取数据
    • put() 将输入存入Buffer中
    • clear() 清空Buffer 本质上是把position 和limit 重置
    • mark() 获取当前position
    • reset() 将当前的position 重置为mark
    • rewind() 重读操作 将position 重新置为0

    测试代码

    public class NioBufferDemo {
    
        public static void main(String[] args) {
            // 使用Buffer.allocate 创建一个指定大小的buffer
            IntBuffer intBuffer = IntBuffer.allocate(5);
    
            for (int i = 0; i < intBuffer.capacity(); i++) {
                int i1 = i * 2;
                System.out.println(String.format("put %d in buffer", i1));
                intBuffer.put(i1);
            }
    
            // buffer 读写模式切换 一定要记得翻转一下 将指针重新指向开头
            // 翻转的本质就是将limit = position 然后 position 置0  mark改为-1
            intBuffer.flip();
    		// 是否有剩余
            while (intBuffer.hasRemaining()) {
                System.out.println("take buffer => "+intBuffer.get());
            }
        }
    
    }
    
  • Channel通道

    channel是NIO三大组件中的用于数据传输的组件。类似于传统BIO中的流,但是与BIO不同的是传统的BIO Inputstream Outputstream是单向的,NIO channel是双向的能读能写,实现异步读写数据,面向缓冲区Buffer。

    Channel是NIO中的一个接口

    // java.nio.channels.Channel
    public interface Channel extends Closeabl
    
    • 常用主要实现类

      • FileChannel 文件读写操作
      • DatagramChannel UDP数据读写操作
      • ServerSocketChannel TCP读写操作类似传统的ServerSocket
      • SocketChannel TCP读写操作类似传统的Socket
    • FileChannel 核心方法

      public int read(ByteBuffer dst)//从通道中读取数据到Buffer中
      public int write(ByteBuffer src)// 将Buffer中数据写入channel
      public long transferFrom(ReadableByteChannel src,
                               long position, 
                               long count) //从目标通道复制数据到当前通道
      public long transferTo(long position, 
                             long count,
                             WritableByteChannel target) // 将当前通道数据写入到目标通道
      
    • FileChannel代码演示

      	/**
           * 数据读取    channel.read(buffer);
           * @throws IOException
           */
          private static void readFromChannel() throws IOException {
              File file = new File("1.txt");
              FileInputStream fileInputStream = new FileInputStream(file);
              // 通过inputStream.getChannel() 获取当前文件的FileChannel
              FileChannel channel = fileInputStream.getChannel();
              // 创建一个buffer 用于 读数据
              ByteBuffer buffer = ByteBuffer.allocate((int) file.length());
              // 把Channel中的数据读到buffer中
              channel.read(buffer);
              // 打印
              System.out.println(new String(buffer.array()));
          }
      
      	 /**
           * 数据写入  channel.write(byteBuffer);
           * @throws IOException
           */
          private static void writeToChannel() throws IOException {
              // 模拟内从
              String content = "hello world netty is good!";
              // 创建一个buffer 用于保存数据
              ByteBuffer byteBuffer = ByteBuffer.allocate(content.length());
              // 将数据写入到buffer中
              byteBuffer.put(content.getBytes());
              // 注意一定要flip!!!!读写切换 想指针重新指向开头 不然写入不到任何数据
              byteBuffer.flip();
              File file = new File("output.txt");
              // 创建文件输出流
              FileOutputStream fileOutputStream = new FileOutputStream(file);
              // 获取channel
              FileChannel channel = fileOutputStream.getChannel();
              // 将buffer中的数据写入到channel中
              channel.write(byteBuffer);
              // 关闭流自动关闭channel
              fileOutputStream.close();
          }
      
       	/**
           * 文件拷贝 transferFrom
           * @throws IOException
           */
          private static void transferFromApi() throws IOException {
              File src =  new File("1.txt");
              FileInputStream inputStream = new FileInputStream(src);
              File dest =  new File("1_copy.txt");
              FileOutputStream outputStream = new FileOutputStream(dest);
      
              FileChannel inputChannel = inputStream.getChannel();
              FileChannel outputChannel = outputStream.getChannel();
              // channel实现文件拷贝
              outputChannel.transferFrom(inputChannel,0,src.length());
      
              inputStream.close();
              outputStream.close();
          }
      
      // 基于NIO实现的文件拷贝方法
      /**
           * 通过NIO实现文件复制
           * @param src
           * @param dest
           * @throws IOException
           */
          private static void copyByNIO(String src, String dest) throws IOException {
              File file = new File(src);
              FileInputStream inputStream = new FileInputStream(file);
              FileChannel inputChannel = inputStream.getChannel();
      
              FileOutputStream outputStream = new FileOutputStream(new File(dest));
              FileChannel outputChannel = outputStream.getChannel();
              // 创建buffer 数据中间保存的容器
              ByteBuffer buffer = ByteBuffer.allocate(2);
      
              while (true) {
                  // 清空buffer
                  buffer.clear();
                  int read = inputChannel.read(buffer);
                  // 如果已经读完了
                  if (read < 0) {
                      break;
                  }
                  // 翻转
                  buffer.flip();
                  // 写入
                  outputChannel.write(buffer);
              }
      
              inputStream.close();
              outputStream.close();
          }
      

猜你喜欢

转载自blog.csdn.net/woshiwjma956/article/details/106719094