文档章节

java NIO之Buffer基础

 王CHAO
发布于 2016/05/14 08:03
字数 1054
阅读 8
收藏 0
点赞 2
评论 0

这段时间空闲下来,学习了下nio的一些东西,记录下来,以加深自己的理解和记忆。 

Java NIO 由以下几个核心部分组成: 

  • Channels
  • Buffers
  • Selectors


虽然Java NIO 中除此之外还有很多类和组件,但在我看来,Channel,Buffer 和 Selector 构成了核心的API。 
Buffers 缓冲区,以及缓冲区如何工作,是所有 I/O 的基础。所谓“输入/输出”讲的无非就是把数据移 进或移出缓冲区。 

概念:实际上缓冲区就是一个包含在对象里的基本数据元素数组 
属性:所有的缓冲区都具有四个属性来提供关于其所包含的数据元素的信息。它们是: 

  • 容量(Capacity) 缓冲区能够容纳的数据元素的最大数量。这一容量在缓冲区创建时被设定,并且永远不能被改变。
  • 上界(Limit) 缓冲区的第一个不能被读或写的元素。或者说,缓冲区中现存元素的计数。
  • 位置(Position) 下一个要被读或写的元素的索引。位置会自动由相应的get( )和put( )函数更新。
  • 标记(Mark) 一个备忘位置。调用mark( )来设定mark = postion。调用reset( )设定position = mark。标记在设定前是未定义的(undefined)。

看下图 新创建一个ByteBuffer 

 

我们通过 ByteBuffer.allocate(11) 方法创建一个 10 个 byte 的数组缓冲区,初始状态如上图所示,position 的位置为 0,capacity 和 limit 默认都是数组长度。当我们写入 5 个字节时位置变化如下图所示: 

 


这时如果我们想在不丢失位置的情况下进行一些修改,比如说将hello更改为MelloW 
可以这样实现 
buffer.put(0,(byte)'M').put((byte)'w'); 
修改后的Buffer图像如下图 


 

如果我们想将缓冲区的 5 个字节数据写入 Channel 通信信道,我们需要调用 byteBuffer.flip() 方法,数组的状态又发生如下变化 

 


还有一个方法 rewind (),会重置position的位置为0 但不改变limit的位置,可以使用rewind()后退,重读已经被翻转的缓冲区中的数据。 

 

  • 一旦读完Buffer中的数据,需要让Buffer准备好再次被写入。可以通过clear()或compact()方法来完成。
  • 如果调用的是clear()方法,position将被设回0,limit被设置成 capacity的值。换句话说,Buffer 被清空了。但这个时候Buffer中的数据并未清除,只是这些标记告诉我们可以从哪里开始往Buffer里写数据。


看下面代码

Java代码 

 收藏代码

  1. public static void main(String[] argv) throws Exception {  
  2.         CharBuffer buffer = CharBuffer.allocate(20);  
  3.         System.out.println("初始化时候:position="+buffer.position()+" limit="+buffer.limit());  
  4.         fillBuffer(buffer,"hello");  
  5.         System.out.println("填入hello以后:position="+buffer.position()+" limit="+buffer.limit());  
  6.         buffer.put(0,'M').put('w');  
  7.         System.out.println("修改成Mellow后:position="+buffer.position()+" limit="+buffer.limit());  
  8.         buffer.flip();  
  9.         System.out.println("翻转后:position="+buffer.position()+" limit="+buffer.limit());  
  10.         buffer.clear();  
  11.         System.out.println("clear后:position="+buffer.position()+" limit="+buffer.limit());  
  12.         buffer.position(0);  
  13.         while (buffer.hasRemaining()) {  
  14.             System.out.println(buffer.get());  
  15.         }  
  16.     }private static void fillBuffer(CharBuffer buffer) {  
  17.         String string = "MY TEST BUFFER";  
  18.         for (int i = 0; i < string.length(); i++) {  
  19.             buffer.put(string.charAt(i));  
  20.         }  
  21.     }  
  22.   
  23. 结果:  
  24. 初始化时候:position=0 limit=20  
  25. 填入hello以后:position=5 limit=20  
  26. 修改成Mellow后:position=6 limit=20  
  27. 翻转后:position=0 limit=6  
  28. clear后:position=0 limit=20  
  29. M  
  30. e  
  31. l  
  32. l  
  33. o  
  34. w  


从上面例子可以看出clear后实际上buffer中数据还是存在的 
如果Buffer中有一些未读的数据,调用clear()方法,数据将“被遗忘”,意味着不再有任何标记会告诉你哪些数据被读过,哪些还没有。 
如果Buffer中仍有未读的数据,且后续还需要这些数据,但是此时想要先先写些数据,那么使用compact()方法。 
看下面代码: 

Java代码 

 收藏代码

  1. public static void compactTest(){  
  2.         CharBuffer buffer = CharBuffer.allocate(11);  
  3.         fillBuffer(buffer,"hello world");  
  4.         buffer.position(6);  
  5.         buffer.compact();  
  6.         buffer.put("j");  
  7.         buffer.put("a");  
  8.         buffer.put("v");  
  9.         buffer.put("a");  
  10.         buffer.flip();  
  11.         while (buffer.hasRemaining()) {  
  12.             System.out.print(buffer.get());  
  13.         }  
  14.     }  
  15. 打印结果为worldjava  


compact()方法将所有未读的数据拷贝到Buffer起始处。然后将position设到最后一个未读元素正后面。limit属性依然像clear()方法一样,设置成capacity。现在Buffer准备好写数据了,但是不会覆盖未读的数据。 
其它还有mark()与reset() equals()等方法 就不一一介绍了。 

© 著作权归作者所有

共有 人打赏支持
粉丝 0
博文 5
码字总数 3246
作品 0
东城
Java NIO 系列教程 -- delete

(一) Java NIO 概述 Java NIO 由以下几个核心部分组成: Channels Buffers Selectors 虽然Java NIO 中除此之外还有很多类和组件,但在我看来,Channel,Buffer 和 Selector 构成了核心的A...

数据之美 ⋅ 2013/06/09 ⋅ 4

Java NIO 之 Channel(通道)

历史回顾: Java NIO 概览 Java NIO 之 Buffer(缓冲区) 其他高赞文章: 面试中关于Redis的问题看这篇就够了 一文轻松搞懂redis集群原理及搭建与使用 一 Channel(通道)介绍 通常来说NIO中的所...

山川_84b6 ⋅ 05/15 ⋅ 0

Java NIO之Selector(选择器)

历史回顾: Java NIO 概览 Java NIO 之 Buffer(缓冲区) Java NIO 之 Channel(通道) 其他高赞文章: 面试中关于Redis的问题看这篇就够了 一文轻松搞懂redis集群原理及搭建与使用 超详细的Jav...

山川_84b6 ⋅ 05/16 ⋅ 0

阿里巴巴菜鸟Java一面11个问题,你会几个呢?

近日,w3cschool app开发者头条上分享了阿里菜鸟Java程序员一些面试题。 这吸引了不少程序员小伙伴们的注意。 在分享阿里菜鸟Java程序员面经前,来看下Java面试一些面试经验分享: 0、Java高...

W3Cschool ⋅ 04/03 ⋅ 0

Jenkins 教程(一)实现自动化打包及邮件通知

个人不喜欢装腔作势一堆专业术语放上去,让大多数人看不懂来提升逼格(所谓的专家),所以我简单的介绍jenkins是干啥的。本文使用jenkins,就是让它把git仓库里的东西取出来,然后在jenkins容器...

FantJ ⋅ 05/26 ⋅ 0

java基础io流——配角也风流(不求甚解)

本章简单介绍几个常见的io流派生。 1:数据操作流(操作基本类型数据的流)(理解) 代码示例: 2:内存操作流(理解) 用于处理临时存储信息的,程序结束,数据就从内存中消失。 代码示例: 注:查看...

潇潇漓燃 ⋅ 05/30 ⋅ 0

Java程序员必读书单,家族又添新成员

点击关注异步图书,置顶公众号 每天与你分享IT好书 技术干货 职场知识 参与文末话题讨论,每日赠送异步图书。 ——异步小编 有些革命出其不意地吸引了全世界的眼球。Twitter、Linux操作系统和...

异步社区 ⋅ 05/09 ⋅ 0

面试必看!2018年4月份阿里最新的java程序员面试题目

目录 技术一面(23问) 技术二面(3大块) 性能优化(21点) 项目实战(34块) JAVA方向技术考察点(15点) JAVA开发技术面试中可能问到的问题(17问) 阿里技术面试1 1.Java IO流的层次结构...

美的让人心动 ⋅ 04/16 ⋅ 0

00.java虚拟机的基本结构概念

java虚拟机的基本结构 1、类加载子系统:负责从文件系统或者网络中加载Class信息,加载的信息存放在一块称之为方法区的内存空间。 2、方法区:就是存放类信息、常量信息、常量池信息、包括字...

挚爱冷如烟° ⋅ 05/08 ⋅ 0

深入理解java虚拟机阅读笔记(一)————java内存区域

第二章:Java内存区域与内存溢出 2.2 运行时数据区域 2.2.1 程序计数器: (1)、一块较小的内存空间 (2)、可看做当前线程执行的字节码的行号指示器 (3)、字节码解释器工作时通过改变这个...

qq_37468185 ⋅ 05/10 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

Boost库编译应用

版本:Boost 1.66.0 Windows库编译 官网指南:直接执行bootstrap.bat处理文件即可,可以我却遇到一堆的问题。 环境:Windows 10 + Visual Studio 2017 Boost编译出来库命名 boost库生成文件命...

水海云 ⋅ 22分钟前 ⋅ 0

解决Eclipse发布到Tomcat丢失依赖jar包的问题

如果jar文件是以外部依赖的形式导入的。Eclipse将web项目发布到Tomcat时,是不会自动发布这些依赖的。 可以通过Eclipse在项目上右击 - Propertics - Deployment Assembly,添加“Java Build ...

ArlenXu ⋅ 22分钟前 ⋅ 0

iview tree组件层级过多时可左右滚动

使用vue+iview的tree组件,iview官网iview的tree树形控件 问题描述:tree层级过多时左右不可滚动 问题解决:修改overflow属性值 .el-tree-node>.el-tree-node_children { overflow: vi...

YXMBetter ⋅ 24分钟前 ⋅ 0

分布式锁

1.通过数据库实现 http://www.weizijun.cn/2016/03/17/%E8%81%8A%E4%B8%80%E8%81%8A%E5%88%86%E5%B8%83%E5%BC%8F%E9%94%81%E7%9A%84%E8%AE%BE%E8%AE%A1/ 2.ZK实现:curator-recipes分布式锁的......

素雷 ⋅ 32分钟前 ⋅ 0

Sublime Text3 快捷键

选择类 Ctrl+D 选中光标所占的文本,继续操作则会选中下一个相同的文本。 Alt+F3 选中文本按下快捷键,即可一次性选择全部的相同文本进行同时编辑。举个栗子:快速选中并更改所有相同的变量名...

AndyZhouX ⋅ 39分钟前 ⋅ 0

XamarinAndroid组件教程RecylerView自定义适配器动画

XamarinAndroid组件教程RecylerView自定义适配器动画 如果RecyclerViewAnimators.Adapters命名空间中没有所需要的适配器动画,开发者可以自定义动画。此时,需要让自定义的动画继承Animation...

大学霸 ⋅ 39分钟前 ⋅ 0

eureka 基础(二)

使用Eureka服务器进行身份验证 如果其中一个eureka.client.serviceUrl.defaultZone网址中包含一个凭据(如http://user:password@localhost:8761/eureka)),HTTP基本身份验证将自动添加到您...

明理萝 ⋅ 42分钟前 ⋅ 1

Kubernetes(五) - Service

Kubernetes解决的另外一个痛点就是服务发现,服务发现机制和容器开放访问都是通过Service来实现的,把Deployment和Service关联起来只需要Label标签相同就可以关联起来形成负载均衡,基于kuberne...

喵了_个咪 ⋅ 42分钟前 ⋅ 0

更新队友POM文件后报错

打开报错的地方的pom及其引用方法所在文件的pom,观察其版本号是否一致,不一致进行更改

森火 ⋅ 55分钟前 ⋅ 0

IDEA使用sonarLint

一、IDEA如何安装SonarLint插件 1.打开 Idea 2.点击【File】 3.点击【Settings】 4.点击【Plugins】 5.在搜索栏中输入“sonarlint”关键字 6.点击【Install】进行安装 7.重启Idea 二、IDEA如...

开源中国成都区源花 ⋅ 今天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部