zoukankan      html  css  js  c++  java
  • Java NIO

    ByteBuffer

    ByteBuffer

    image

    使用byte[]数组存储

    1. capacity
      数组长度

    2. limit
      第一个不可读取或写入的index

    3. mark
      标记当前position,通过reset返回到mark位置

    4. position
      下一个要读取或写入的index

    5. int remaining()
      获取剩余容量: limit-position

    0<mark<position<limit<capacity

    1. 判断缓冲区是否只读
    ByteBuffer byteBuffer = ByteBuffer.wrap(new byte[] {1, 2, 3, 4, 5, 6});
    System.out.println(byteBuffer.isReadOnly());  // false
    
    1. 直接缓冲区
      image
    ByteBuffer byteBuffer = ByteBuffer.wrap(new byte[] {1, 2, 3, 4, 5, 6});
    System.out.println(byteBuffer.isDirect());  // false
    
    1. 还原缓冲区状态
    public final Buffer clear() {
        position = 0;	
        limit = capacity;
        mark = -1;
        return this;
    }
    

    position=1; limit=capacity; mark=-1;

    1. 对缓冲区进行反转 flip()
      将指针设置为0,mark设置为-1,当前位置设置为不可读写的位置
      将限制设置为当前位置
    public final Buffer flip() {
        limit = position;
        position = 0;
        mark = -1;
        return this;
    }
    
    //  测试
    ByteBuffer buffer = ByteBuffer.allocateDirect(10);
    buffer.put(new byte[] {1, 2, 3, 4, 5, 6}, 2, 3);
    
    //        buffer.rewind();
    buffer.flip();
    while (buffer.hasRemaining())
    {
        System.out.println(buffer.get());
    }
    // 3  4  5
    
    1. remind()
      将指针设置为0,mark设置为-1
    public final Buffer rewind() {
        position = 0;
        mark = -1;
        return this;
    }
    
    //  测试
    ByteBuffer buffer = ByteBuffer.allocateDirect(10);
    buffer.put(new byte[] {1, 2, 3, 4, 5, 6}, 2, 3);
    
    buffer.rewind();
    while (buffer.hasRemaining())
    {
        System.out.println(buffer.get());
    }
    // 3  4  5 0 0 0 0 0 0 0
    
    1. putLong()
      将8个字节put到缓冲区中,如putLong(1) --> 1 2 3 4 5 6 7 8
      高位/低位 array() 字节顺序

    2. asCharBuffer 视图转换
      两个字节转为一个字符 e.g

    ByteBuffer buffer = ByteBuffer.allocateDirect(10);
    buffer.put(new byte[] {0, 98, 0, 99, 0, 100, 0, 101, 0, 102});
    
    buffer.rewind();
    
    CharBuffer charBuffer = buffer.asCharBuffer();
    while (charBuffer.hasRemaining())
    {
        System.out.println(charBuffer.get());
    }
    // b c d e f
    

    直接缓冲区和堆缓冲区

    • 直接缓冲区的内存分配和释放的成本要高于非直接缓冲区。因此不要频繁的创建直接缓冲区
    1. slice()
      内存共享缓冲区

    2. 压缩缓冲区

    image

     byte[] bytes = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
     ByteBuffer buffer = ByteBuffer.wrap(bytes);
    
     buffer.position(2);
     buffer.compact();
     System.out.println("current position:" + buffer.position());  // 8
     buffer.rewind();
    
     while (buffer.hasRemaining())
     {
         System.out.println(buffer.get());
     }
    
    3
    4
    5
    6
    7
    8
    9
    10
    9
    10
    
    1. duplicate 复制缓冲区
      新缓冲区的内容一样,内存共享

    通道和FileChannel的使用

    通道概述

    通道:数据传输的通路

    NIO是将数据放在缓冲区进行管理,再利用通道进行数据传输到目的地

    channel

    image

    jdk1.8 通道子接口

    • AsynchronousChannel
    • AsynchronousByteChannel
    • ReadableByteChannel
    • ScatteringByteChannel
    • WriteableByteChannel
    • GatheringByteChannel
    • ByteChannel
    • SeekableByteChannel
    • NetworkChannel
    • MulticastChannel
    • InterruptipleChannel
    1. AsynchronousChannel
      使通道支持异步IO操作
      (1)Future operation()
      Future用来判断IO操作是否完成,或者等待完成
      (2)回调的方式
      void operation(... A attachment, CompletionHandler<V, supper A> handler)

    2. ReadableByteChannel
      只允许一个线程read,第二个会被阻塞
      1) 将通道当前位置读到ByteBuffer中
      2) read(ByteBuffer )是同步的

    3. ScatteringByteChannel
      从通道中读取字节到多个缓冲区

    public long read(ByteBuffer[] dsts) throws IOException;
    
    1. GatheringByteChannel
      将多个缓冲区的内容写到通道中

    2. ByteChannel
      整合ReadableByteChannel和WriteableChannel

    3. SeekableByteChannel
      允许position改变

    4. NetworkChannel
      与Socket进行关联
      bind(SocketAddress)

    FilChannel

    Charset charset = Charset.forName("GBK");//Java.nio.charset.Charset处理了字符转换问题。它通过构造CharsetEncoder和CharsetDecoder将字符序列转换成字节和逆转换。
    CharsetDecoder decoder = charset.newDecoder();
    
    System.out.println(System.getProperty("user.dir"));
    FileInputStream fis = new FileInputStream(System.getProperty("user.dir")+"/src/main/resources/aa.txt");
    FileChannel fileChannel = fis.getChannel();
    ByteBuffer byteBuffer = ByteBuffer.allocate(5);
    CharBuffer cb = CharBuffer.allocate(5);
    while (fileChannel.isOpen() && fileChannel.read(byteBuffer) != -1)
    {
        System.out.println("length:" + byteBuffer.position());
        byteBuffer.flip();
        decoder.decode(byteBuffer, cb, false);
        cb.flip();
        while (cb.hasRemaining())
        {
            System.out.println(cb.get());
        }
        cb.clear();
        byteBuffer.clear();
    }
    
  • 相关阅读:
    mysql初始化/usr/local/mysql/bin/mysqld: error while loading shared libraries: libnuma.so.1: cannot open shared object file: No such file or directory
    centos重启出现type Control-D to continue【fsck使用】
    find 常用命令
    保持简单----纪念丹尼斯•里奇(Dennis Ritchie)
    最有效的五个方法,彻底控制你的负面情绪,你有吗
    ERROR 1366 (HY000): Incorrect string value: 'xE9x83x91xE5xB7x9E' for column 'aa' at row 1 MySQL 字符集
    Got fatal error 1236 from master when reading data from binary log: 'Could not find first log file name in binary log index file'
    mysql从5.6升级到5.7后出现 Expression #1 of ORDER BY clause is not in SELECT list,this is incompatible with DISTINCT
    mysqld_safe error: log-error set to '/data/log/mysqld.log', however file don't exists. Create writable for user 'mysql'.The server quit without updating PID file (/data/mysql/mysqld.pid)
    ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: YES)
  • 原文地址:https://www.cnblogs.com/zhuxiang1633/p/15076267.html
Copyright © 2011-2022 走看看