前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >NIO之缓冲区【基础内容】

NIO之缓冲区【基础内容】

作者头像
用户4919348
发布2019-04-18 17:16:59
5050
发布2019-04-18 17:16:59
举报
文章被收录于专栏:波波烤鸭波波烤鸭

  我们知道NIO的三大核心是buffer,channel和selector,本文开始详细介绍下buffer

缓冲区Buffer

1.缓冲区介绍

  一个Buffer对象是固定数量的数据的容器。其作用是一个存储器,或者分段运输区,在这里数据可被存储并在之后用于检索。缓冲区可以写满和释放。对于每个非布尔原始数据类型都有一个缓冲区类。尽管缓冲区作用于它们存储的原始数据类型,但缓冲区十分倾向于处理字节。   缓冲区的工作与通道紧密联系。通道是 I/O 传输发生时通过的入口,而缓冲区是这些数据传输的来源或目标。   下图是Buffer的类层次图。在顶部是通用Buffer类,Buffer 定义所有缓冲区类型共有的操作,无论是它们所包含的数据类型还是可能具有的特定行为。这一共同点将会成为我们的出发点。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2.缓冲区操作

  概念上,缓冲区是包在一个对象内的基本数据元素数组。Buffer 类相比一个简单数组的优点是它将关于数据的数据内容和信息包含在一个单一的对象中。Buffer 类以及它专有的子类定义了一个用于处理数据缓冲区的 API

2.1 创建缓冲区

  新的缓冲区是由分配或包装操作创建的.

方式

说明

分配

创建一个缓冲区对象并分配一个私有的空间来存储容量大小的数据元素

包装

创建一个缓冲区对象但不分配任何空间来存储数据元素,使用我们单独提供的数据作为存储空间来存储缓冲区的数据元素

分配方式:

代码语言:javascript
复制
// 创建一个ByteBuffer,容量为10
ByteBuffer byteBuffer = ByteBuffer.allocate(10);
在这里插入图片描述
在这里插入图片描述

包装方式:

代码语言:javascript
复制
byte[] array = new byte[10];
ByteBuffer.wrap(array);
在这里插入图片描述
在这里插入图片描述

2.2 属性

  所有的缓冲区都具有四个属性来提供关于其所包含的数据元素的信息。

在这里插入图片描述
在这里插入图片描述

属性

说明

容量(Capacity)

缓冲区能够容纳的数据元素的最大数量,缓冲区创建时被设定,永远不能被改变

上界(Limit)

缓冲区第一个不能被读或写的元素,或者说缓冲区中现存元素的计数

位置(Position)

下一个要被读或写的元素的索引,位置会自动由相应的get()和put()方法更新

标记(Mark)

一个备忘位置,调用mark()方法来设定,mark=position,调用reset方法设定position=mark。标记在设定前是未定义的(undefined)

四个属性之前总是遵循以下关系:

代码语言:javascript
复制
mark <= position <= limit <= capacity

举例:

代码语言:javascript
复制
// 创建一个ByteBuffer,容量为10
ByteBuffer byteBuffer = ByteBuffer.allocate(10);
在这里插入图片描述
在这里插入图片描述

  位置被设为0,而且容量和上界被设为10,刚好经过缓冲区能够容纳的最后一个字节。标记最初未定义。容量是固定的,但另外的三个属性可以在使用缓冲区时改变

2.3 缓冲区API介绍

  接下来我们先看下Buffer中提供的方法

代码语言:javascript
复制
package java.nio; 
public abstract class Buffer { 
 public final int capacity( ) 
 public final int position( ) 
 public final Buffer position (int newPosition)
 public final int limit( ) 
 public final Buffer limit (int newLimit) 
 public final Buffer mark( ) 
 public final Buffer reset( ) 
 public final Buffer clear( ) 
 public final Buffer flip( ) 
 public final Buffer rewind( ) 
 public final int remaining( ) 
 public final boolean hasRemaining( ) 
 public abstract boolean isReadOnly( ); 
}

put方法   '存取’也就将数据保存到缓冲区中及从缓冲区中取出数据,在Buffer类中并没有提供get和put方法,这两个方法在具体的Buffer子类中有提供,比如ByteBuffer.如下

代码语言:javascript
复制
public abstract class ByteBuffer 
 extends Buffer implements Comparable 
{ 
 // This is a partial API listing 
 public abstract byte get( ); 
 public abstract byte get (int index); 
 public abstract ByteBuffer put (byte b); 
 public abstract ByteBuffer put (int index, byte b); 
}

保存数据到缓冲区

代码语言:javascript
复制
public static void main(String[] args) {
	// 创建一个ByteBuffer,容量为10
	ByteBuffer byteBuffer = ByteBuffer.allocate(10);
	// 看一下初始时4个核心变量的值
	System.out.println("初始时-->limit--->" + byteBuffer.limit());
	System.out.println("初始时-->position--->" + byteBuffer.position());
	System.out.println("初始时-->capacity--->" + byteBuffer.capacity());
	System.out.println("初始时-->mark--->" + byteBuffer.mark());

	System.out.println("--------------------------------------");

	// 添加一些数据到缓冲区中
	String s = "bobo";
	byteBuffer.put(s.getBytes());

	// 看一下初始时4个核心变量的值
	System.out.println("put完之后-->limit--->" + byteBuffer.limit());
	System.out.println("put完之后-->position--->" + byteBuffer.position());
	System.out.println("put完之后-->capacity--->" + byteBuffer.capacity());
	System.out.println("put完之后-->mark--->" + byteBuffer.mark());
}

输出:

代码语言:javascript
复制
初始时-->limit--->10
初始时-->position--->0
初始时-->capacity--->10
初始时-->mark--->java.nio.HeapByteBuffer[pos=0 lim=10 cap=10]
--------------------------------------
put完之后-->limit--->10
put完之后-->position--->4
put完之后-->capacity--->10
put完之后-->mark--->java.nio.HeapByteBuffer[pos=4 lim=10 cap=10]
在这里插入图片描述
在这里插入图片描述

flip方法 现在我想要从缓存区拿数据,怎么拿呢?NIO给了我们一个flip()方法。这个方法可以改动position和limit的位置!

在这里插入图片描述
在这里插入图片描述
代码语言:javascript
复制
byteBuffer.flip();
System.out.println("flip完之后-->limit--->" + byteBuffer.limit());
System.out.println("flip完之后-->position--->" + byteBuffer.position());
System.out.println("flip完之后-->capacity--->" + byteBuffer.capacity());
System.out.println("flip完之后-->mark--->" + byteBuffer.mark());
代码语言:javascript
复制
flip完之后-->limit--->4
flip完之后-->position--->0
flip完之后-->capacity--->10
flip完之后-->mark--->java.nio.HeapByteBuffer[pos=0 lim=4 cap=10]
在这里插入图片描述
在这里插入图片描述

一般我们称filp()为“切换成读模式

get方法   get方法读取信息position也会对应的移动!

代码语言:javascript
复制
// 一个字节一个字节的读取
System.out.println((char)byteBuffer.get());
System.out.println((char)byteBuffer.get());
System.out.println((char)byteBuffer.get());
System.out.println((char)byteBuffer.get());
System.out.println("get完之后-->mark--->" + byteBuffer.mark());
// get方法 读取了多少个字节,position就会移动多少位,相应再次重新读取需要flip
byteBuffer.flip();
byte[] b = new byte[byteBuffer.limit()];
// 批量读取数据
byteBuffer.get(b);
System.out.println(new String(b,0,b.length));
System.out.println("get完之后-->mark--->" + byteBuffer.mark());

输出

代码语言:javascript
复制
b
o
b
o
get完之后-->mark--->java.nio.HeapByteBuffer[pos=4 lim=4 cap=10]
bobo

clear方法   数据操作完成后我们还想要继续写入数据,这时我们可以使用clear方法来’清空’缓冲区。数据没有真正被清空,只是被遗忘掉了

在这里插入图片描述
在这里插入图片描述

hasRemaining()   检查position和limit之间是否还有元素。判断是否还有剩余元素

在这里插入图片描述
在这里插入图片描述
代码语言:javascript
复制
// 一个字节一个字节的读取
System.out.println((char)byteBuffer.get());
System.out.println("hasRemaining:"+byteBuffer.hasRemaining());
System.out.println((char)byteBuffer.get());
System.out.println("hasRemaining:"+byteBuffer.hasRemaining());
System.out.println((char)byteBuffer.get());
System.out.println("hasRemaining:"+byteBuffer.hasRemaining());
System.out.println((char)byteBuffer.get());
System.out.println("hasRemaining:"+byteBuffer.hasRemaining());

输出

代码语言:javascript
复制
b
hasRemaining:true
o
hasRemaining:true
b
hasRemaining:true
o
hasRemaining:false

rewind方法   读完一遍数据后,我们还想再读取一遍,此时可以考虑rewind方法 注意他和flip方法的区别

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

通过源码分析会更加清晰些~

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019年04月10日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 缓冲区Buffer
    • 1.缓冲区介绍
      • 2.缓冲区操作
        • 2.1 创建缓冲区
        • 2.2 属性
        • 2.3 缓冲区API介绍
    相关产品与服务
    对象存储
    对象存储(Cloud Object Storage,COS)是由腾讯云推出的无目录层次结构、无数据格式限制,可容纳海量数据且支持 HTTP/HTTPS 协议访问的分布式存储服务。腾讯云 COS 的存储桶空间无容量上限,无需分区管理,适用于 CDN 数据分发、数据万象处理或大数据计算与分析的数据湖等多种场景。
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档