请选择 进入手机版 | 继续访问电脑版
搜索
房产
装修
汽车
婚嫁
健康
理财
旅游
美食
跳蚤
二手房
租房
招聘
二手车
教育
茶座
我要买房
买东西
装修家居
交友
职场
生活
网购
亲子
情感
龙城车友
找美食
谈婚论嫁
美女
兴趣
八卦
宠物
手机

6. 彤哥说netty系列之Java NIO核心组件之Buffer

[复制链接]
查看: 9|回复: 0

1万

主题

2万

帖子

4万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
48014
发表于 2019-12-4 01:36 | 显示全部楼层 |阅读模式
——日拱一卒,不期而至!

6. 彤哥说netty系列之Java NIO核心组件之Buffer  游戏 1648938-20191203223827584-1808446070

你好,我是彤哥,本篇是netty系列的第六篇。
简介

上一章我们一路进修了Java NIO的焦点组件Channel,它可以看做是实体与实体之间的毗连,而且需要与Buffer交互,这一章我们就来进修一下Buffer的特征。
概念

Buffer用于与Channel交互时利用,经过上一章的进修我们晓得,数据从Channel读取到Buffer,大要从Buffer写入Channel。
6. 彤哥说netty系列之Java NIO核心组件之Buffer  游戏 1648938-20191203223827800-165595936

Buffer本质上是一个内存块,可以向里面写入数据,大要从里面读取数据,在Java中它被包装成了Buffer工具,并供给了一系列的方式用于操纵这个内存块。
属性

为了更好地大白Buffer的数据结构,我们必须熟悉它的三个常用属性:

  • capacity:容量
  • position:当前位置
  • limit:限制长度
在读形式和写形式下,position和limit的位置有所不同,见下图:
6. 彤哥说netty系列之Java NIO核心组件之Buffer  游戏 1648938-20191203223828033-1139421956

capacity

Buffer作为一个存储块,是有牢固巨细的,这个牢固巨细我们称作“容量”。
当Buffer写满以后,需要先清空大要读取数据,才华继续写入新的数据。
position

写形式下,position从0起头,每写入一个单元的数据,position进步一位,position最大可到达(capacity-1)的位置。
当Buffer从写形式切换为读形式时,position将重置为0。读取数据时,一样地,position每读取一个单元,进步一位,此时,position最大可到达limit的位置(现实最大可读取的位置是(limit-1))。
limit

写形式下,limit最大值即是capacity。
读形式下,limit最大值即是切换为读形式时position的值,本文根源工从号彤哥读源码。
这里大要有点绕,position类似于数组的下标,是从0起头的,limit表现最大可以读取大要写入的长度,capacity表现最大的容量,limit和capacity不是下标,类似于数组的长度,所以跟position比力需要-1。在写形式下,position指向的是下一个待写入的位置;在读形式下,position指向的是下一个待读取的位置。
典范

Java NIO自带的Buffer典范有:

  • ByteBuffer
  • MappedByteBuffer
  • CharBuffer
  • ShortBuffer
  • IntBuffer
  • LongBuffer
  • FloatBuffer
  • DoubleBuffer
与底子典范一样,每一种Buffer的底子单元长度纷歧样而已。
其中,MappedByteBuffer是一种特别的ByteBuffer,它利用内存映照的方式加载物理文件,并不会耗费齐截巨细的物理内存,是一种间接操纵堆外内存的方式,读写性能比力高。
底子用法

上面我们进修了Buffer的数据结构以及常用的Buffer典范,它们怎样利用呢?常见的用法垂危有四种:

  • 将数据写入Buffer
  • 切换为读形式flip()
  • 从Buffer中读取数据
  • 清空数据并切换为写形式clear()大要compact()
来个栗子

6. 彤哥说netty系列之Java NIO核心组件之Buffer  游戏 1648938-20191203223828370-1339674610
  1. public class FileChannelTest {    public static void main(String[] args) throws IOException {        // 从文件获得一个FileChannel        FileChannel fileChannel = new RandomAccessFile("D:\\object.txt", "rw").getChannel();        // 分派一个Byte典范的Buffer        ByteBuffer buffer = ByteBuffer.allocate(1024);        // 将FileChannel中的数据读出到buffer中,-1表现读取终了        // buffer默以为写形式,本文根源工从号彤哥读源码        // read()方式是相对channel而言的,相对buffer就是写        while ((fileChannel.read(buffer)) != -1) {            // buffer切换为读形式            buffer.flip();            // buffer中能否有未读数据            while (buffer.hasRemaining()) {                // 读取数据                System.out.print((char)buffer.get());            }            // 清空buffer,为下一次写入数据做预备            // clear()会将buffer再次切换为写形式            buffer.clear();        }    }}
复制代码
allocate()

要获得一个Buffer工具,必须先分派它,每个Buffer类都有一个allocate()方式用于分派Buffer工具。
以下示例分派了一个容量为1024的ByteBuffer工具:
  1. ByteBuffer buffer = ByteBuffer.allocate(1024);
复制代码
下面是分派了一个容量为48的CharBuffer的工具:
  1. CharBuffer buf = CharBuffer.allocate(48);
复制代码
将数据写入Buffer

将数据写入Buffer有两种形式:

  • 从Channel读出数据并写入Buffer,也叫从Channel读入Buffer
  • 挪用Buffer自己的put()方式写入数据
从Channel读入Buffer的示例以下:
  1. int bytesRead = inChannel.read(buf); //读入Buffer
复制代码
Buffer自己put()写入数据的示例以下:
  1. buf.put(127);
复制代码
固然,put()有很多差此外典范,比如在特定位置写入,写入不同典范的数据等等,可以在IDEA中按F12检察。
flip()

flip()方式用于将Buffer从写形式切换为读形式,position将切换到0位置,且limit将切换到适才position的位置。
也就是说,position酿成了可读数据的首位,limit表现可以读取的最大数据长度。
从Buffer中读取数据

从Buffer中读取数据也有两种形式:

  • 从Buffer读取数据,并写入Channel,也叫作从Buffer写入Channel
  • 挪用Buffer自己的get()方式读取数据
从Buffer写入Channel的示例以下:
  1. // 本文根源工从号彤哥读源码int bytesWritten = inChannel.write(buf);
复制代码
挪用Buffer自己的get()方式读取数据的示例以下:
  1. byte aByte = buf.get();   
复制代码
固然,get()有很多差此外典范,比如从特定的位置读取,读取不同典范的数据等等,可以在IDEA中按F12检察。
rewind()

rewind()方式会重置position为0,但limit连结稳定,是以可以用来重新读取数据。凡是是在重新读取数据之前挪用。
clear()

clear()方式用于清空全部Buffer,并将Buffer从读形式切换回写形式,且position归位到0位置。
compact()

compact()方式用于清空已读取的数据,并将未读取的数据移至Buffer的头部,position的位置移动到重新起头盘算的未读取的数据的下一个位置,它也会将Buffer从读形式切换回写形式。
mark() 和 reset()

mark()方式用于标志给定位置,然后可以在以后经过reset()方式重新回到mark的位置,示例以下:
  1. buffer.mark();//屡次挪用buffer.get(),例如在分解进程中。buffer.reset(); //将位置重新设备为标志。
复制代码
总结

本日我们进修了Java NIO焦点组件Buffer,它经常跟Channel团结起来利用。讲到这里我们不停在利用FileChannel在举例,那末它们到底跟收集编程有什么关系呢?请听下回分化。
参考

http://tutorials.jenkov.com/java-nio/channels.html
末端,也接待来我的工从号彤哥读源码系统地进修源码&架构的常识。
6. 彤哥说netty系列之Java NIO核心组件之Buffer  游戏 1648938-20191203223829554-1745663432


免责声明:假如加害了您的权益,请联系站长,我们会实时删除侵权内容,感谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Copyright © 2006-2014 妈妈网-中国妈妈第一,是怀孕、育儿、健康等知识交流传播首选平台 版权所有 法律顾问:高律师 客服电话:0791-88289918
技术支持:迪恩网络科技公司  Powered by Discuz! X3.2
快速回复 返回顶部 返回列表