×

10分钟了解NIO的Buffer

我的笔记 我的笔记 发表于2020-05-31 21:35:16 浏览2917 评论2

2人参与发表评论

1、Buffer的基础用法

package com.fyd.nio;

import java.nio.IntBuffer;

/***
 * @Author付亚东
 * @Date 2020/5/26 22:00
 ****/
public class BasicBuffer {
    public static void main(String[] args) {
        //buffer简单说明
        //创建一个buffer,可以存放5个int
        IntBuffer intBuffer = IntBuffer.allocate(5);
        //向buffer中存放数据
        intBuffer.put(10);
        intBuffer.put(11);
        intBuffer.put(12);
        intBuffer.put(13);
        intBuffer.put(14);
        //向buffer中取数据
        //将buffer切换状态,读写切换
        intBuffer.flip();

        while (intBuffer.hasRemaining()){
            System.out.println(intBuffer.get());
        }
    }
}

2、Buffer只读模式

package com.fyd.nio;

import java.nio.ByteBuffer;

/***
 * @Author付亚东
 * @Date 2020/5/31 17:22
 ****/
public class ReadOnlyBuffer {
    public static void main(String[] args) {
        ByteBuffer byteBuffer = ByteBuffer.allocate(64);
        for (int i=0;i<64;i++){
            byteBuffer.put((byte) i);
        }
        byteBuffer.flip();
        //只读的buffer
        ByteBuffer reasOnlyBuffer = byteBuffer.asReadOnlyBuffer();
        System.out.println(reasOnlyBuffer.getClass());
        while (reasOnlyBuffer.hasRemaining()){
            System.out.println(reasOnlyBuffer.get());
        }
        //不能put
    }
}


3、Buffer的put和get有顺序,并且类型要一致

package com.fyd.nio;

import java.nio.ByteBuffer;

/***
 * @Author付亚东
 * @Date 2020/5/31 17:18
 ****/
public class NIOByteBufferPutGet {
    public static void main(String[] args) {
        ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
        byteBuffer.putInt(100);
        byteBuffer.putChar('你');
        byteBuffer.putLong(2);
        byteBuffer.putShort((short) 3);
        byteBuffer.flip();
        System.out.println(byteBuffer.getInt());
        System.out.println(byteBuffer.getChar());
        System.out.println(byteBuffer.getLong());
        System.out.println(byteBuffer.getShort());
    }
}

4、MappedByteBuffer可以让文件直接在内存(堆外内存)做修改

package com.fyd.nio;

import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;

/***
 * @Author付亚东
 * @Date 2020/5/31 17:26
 * 1、MappedByteBuffer可以让文件直接在内存(堆外内存)做修改,操作系统并不需要拷贝一次
 * 2、
 ****/
public class MapperdByteBufferTest {
    public static void main(String[] args) throws Exception{
        //MappedByteBuffer mappedByteBuffer =
        RandomAccessFile randomAccessFile = new RandomAccessFile("d:\\test.txt","rw");

        FileChannel fileChannel = randomAccessFile.getChannel();
        /**
         * 参数1:FileChannel.MapMode.READ_WRITE  使用读写模式
         * 参数2:0  可以修改的起始位置
         * 参数3:5  映射到内存的大小(不是索引位置),即将 test.txt的多少个字节映射到内存
         *          可以直接修改的范围就是0-5
         */
        MappedByteBuffer map = fileChannel.map(FileChannel.MapMode.READ_WRITE, 0, 5);
        map.put(0,(byte)'H');
        map.put(2,(byte)'L');
        randomAccessFile.close();
        fileChannel.close();
    }
}

5、Buffer的分散和聚合

package com.fyd.nio;

import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Arrays;

/***
 * @Author付亚东
 * @Date 2020/5/31 19:49
 * Scattering:将数据写入到buffer时,可以采用buffer数组,依次写入【分散】
 * Gathering:从buffer读取数据时,也可以采用buffer数组,依次读 【聚合】
 ****/
public class NIOScatteringAndGathering  {
    public static void main(String[] args)throws  Exception {
        //使用serversocketchannel
        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
        InetSocketAddress inetSocketAddress = new InetSocketAddress(7777);
        //绑定端口到socket 启动
        serverSocketChannel.bind(inetSocketAddress);

        //创建buffer数组
        ByteBuffer[] byteBuffers = new ByteBuffer[2];
        byteBuffers[0] = ByteBuffer.allocate(5);
        byteBuffers[1] = ByteBuffer.allocate(3);
        //等待客户端链接
        SocketChannel socketChannel = serverSocketChannel.accept();
        int messageLength = 8;//假定从客户端接收8个字节
        while (true){
            int byteRead = 0;
            while (byteRead<messageLength){
                socketChannel.read(byteBuffers);
                byteRead+=1;//累计读取的字节数
                System.out.println("byteRead"+byteRead);
                //使用流打印。看看当前buffer 的position和limit
                Arrays.asList(byteBuffers).stream().map(byteBuffer -> "position"+byteBuffer.position()+
                        "limit"+byteBuffer.limit());
            }
            //将所有的buffer进行反转
            Arrays.asList(byteBuffers).stream().map(byteBuffer -> byteBuffer.flip());
            //将数据读出显示到客户端
            long byteWrite = 0;
            while (byteWrite<messageLength){
                long l = socketChannel.write(byteBuffers);
                byteWrite+=1;
            }
            //将所有的buffer进行clean
            Arrays.asList(byteBuffers).stream().map(byteBuffer -> byteBuffer.clear());
            System.out.println("byteRead="+byteRead+"byteWrite="+byteWrite);

        }
    }
}






我的笔记博客版权我的笔记博客版权