nio简单例子

1 篇文章 0 订阅

缓冲区底层就是数组用于存储不同的数据类型(boolean除外)

    //ByteBuffer
    //CharBuffer
    //ShortBuffer
    //IntBuffer
    //LongBuffer
    //FloatBuffer
    //DoubleBuffer
/*
* 上述缓冲区通过allocate方法获取缓冲区
* 缓冲区存取数据两个方法是put和get
* private int mark = -1;
* private int position = 0;缓冲区中正在操作数据的位置
* private int limit;缓冲区中可以操作数据的大小
* private int capacity;表示缓冲区中最大存储量
* */
ByteBuffer allocate = ByteBuffer.allocate(1024);
public static ByteBuffer allocate(int capacity) {
    if (capacity < 0)
        throw new IllegalArgumentException();
    return new HeapByteBuffer(capacity, capacity);
}

HeapByteBuffer(int cap, int lim) {            // package-private

    super(-1, 0, lim, cap, new byte[cap], 0);
    /*
    hb = new byte[cap];
    offset = 0;
    */
}

Allocate是非直接缓冲区,建立在jvm内存中,中间需要通过copy数据到操作系统内核中再读取
allocatedirect是直接缓冲区,直接建立在啊物理内存中,能够提高效率,零拷贝
相当于在传输时开辟了一块公共的空间,大家都可以访问

传统的bio会阻塞其他用户,如果开辟其他线程服务,大量访问进行时将会拖垮cpu

使用非直接缓冲区完成文件读写

//利用通道完成文件复制
FileInputStream fileInputStream1 = new FileInputStream("1.jpg");
FileOutputStream fileOutputStream = new FileOutputStream("2.jpg");

//获取通道
FileChannel putchannel = fileInputStream1.getChannel();
FileChannel outchannel = fileOutputStream.getChannel();
//获取缓冲区
ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
//将通道中的数据存入缓冲区
while(putchannel.read(byteBuffer)!=-1){
    //切换到读取数据的模式
    byteBuffer.flip();
    //将缓冲区中的数据写入通道
    outchannel.write(byteBuffer);
    //清空缓冲区继续
    byteBuffer.clear();
}

outchannel.close();
putchannel.close();
fileInputStream1.close();
fileOutputStream.close();

读写速度慢

直接缓冲区读写数据

FileChannel open = FileChannel.open(Paths.get("1.jpg"), StandardOpenOption.READ);
 FileChannel write = FileChannel.open(Paths.get("2.jpg"),StandardOpenOption.WRITE,StandardOpenOption.READ,StandardOpenOption.CREATE_NEW);

MappedByteBuffer map = open.map(FileChannel.MapMode.READ_ONLY, 0, open.size());
MappedByteBuffer map1 = write.map(FileChannel.MapMode.READ_WRITE, 0, open.size());
byte[] b = new byte[map.limit()];
map.get(b);
map1.put(b);
open.close();
write.close();
//使用直接缓冲区读写数据时不稳定,有时jvm垃圾回收机制不能及时释放资源导致卡内存
//直接缓冲区简单方式:
FileChannel open = FileChannel.open(Paths.get("1.jpg"), StandardOpenOption.READ);
FileChannel write = FileChannel.open(Paths.get("3.jpg"),StandardOpenOption.WRITE,StandardOpenOption.CREATE);
open.transferTo(0,open.size(),write);
open.close();
write.close();

分散读取与聚集写入

//分散读取,聚集写入
try (RandomAccessFile randomAccessFile = new RandomAccessFile("1.txt", "rw")) {
    //获取通道
    FileChannel fileChannel  = randomAccessFile.getChannel();
    //分配缓冲区
    ByteBuffer buf1 = ByteBuffer.allocate(1);
    ByteBuffer buf2 = ByteBuffer.allocate(1024);
    //放入缓冲区数组
    ByteBuffer[] b = new ByteBuffer[]{buf1,buf2};
    //分散读取
    fileChannel.read(b);
    for (ByteBuffer byteBuffer:b)
    {
        byteBuffer.flip();

    }
    System.out.println(new String(b[0].array(),0,b[0].limit()));
    System.out.println("-------------------------------------------");
    System.out.println(new String(b[1].array(),0,b[1].limit()));
    //聚集写入
    RandomAccessFile file2 = new RandomAccessFile("2.txt","rw");
    FileChannel channel = file2.getChannel();
    channel.write(b);

}

Nio字符集解决乱码

//反射获取对象
Charset charset  =Charset.forName("GBK");
//获取编码器
CharsetEncoder charsetEncoder = charset.newEncoder();
//获取解码器
CharsetDecoder charsetDecoder = charset.newDecoder();
//字符非直接缓冲区
CharBuffer charBuffer = CharBuffer.allocate(1024);
charBuffer.put("你好!");
charBuffer.flip();
//编码器编码
ByteBuffer encode = charsetEncoder.encode(charBuffer);
for (int i =0;i<6;i++)
{
    System.out.println(encode.get());
}
//解码器解码
encode.flip();
CharBuffer decode = charsetDecoder.decode(encode);
System.out.println(decode.toString());

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

皮特猫.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值