博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
JDK NIO包中Buffer基本使用
阅读量:2492 次
发布时间:2019-05-11

本文共 8131 字,大约阅读时间需要 27 分钟。

Buffer(缓冲区)

在JDK NIO的模型中,所有的I/O都要缓冲,不再向输出流写入数据和从输入流读取数据,而是要从缓冲区中读写数据,像在缓冲流中一样,缓冲区可能就是字节数组。

Java的所有基本数据类型都有特定的Buffer子类:ByteBuffer、CharBuffer、ShortBuffer、IntBuffer、LongBuffer、FloatBuffer、DoubleBuffer。不过在网络编程中几乎只会使用ByteBuffer。

Buffer的结构

位置(position)

缓冲区中将读取或者写入的下一个位置,这个位置值从0开始计,最大值等于缓冲区的大小,可以用下面两个方法获取和设置:

/**     * Returns this buffer's position.     *     * @return  The position of this buffer     */    public final int position() {
return position; } /** * Sets this buffer's position. If the mark is defined and larger than the * new position then it is discarded. * * @param newPosition * The new position value; must be non-negative * and no larger than the current limit * * @return This buffer * * @throws IllegalArgumentException * If the preconditions on newPosition do not hold */ public final Buffer position(int newPosition) {
if ((newPosition > limit) || (newPosition < 0)) throw new IllegalArgumentException(); position = newPosition; if (mark > position) mark = -1; return this; }

容量(capacaity)

缓冲区可以保存的元素的最大数目,容量值在创建缓冲区时设置,此后不能改变,可以用以下方法读取:

/**     * Returns this buffer's capacity.     *     * @return  The capacity of this buffer     */    public final int capacity() {
return capacity; }

限度(limit)

缓冲区中可访问数据的末尾位置,只要不改变限度,就无法读/写超过这个位置的数据,即使缓冲区有更大的容量也没有用,限度可以用下面两个方法获取和设置:

/**     * Returns this buffer's limit.     *     * @return  The limit of this buffer     */    public final int limit() {
return limit; } /** * Sets this buffer's limit. If the position is larger than the new limit * then it is set to the new limit. If the mark is defined and larger than * the new limit then it is discarded. * * @param newLimit * The new limit value; must be non-negative * and no larger than this buffer's capacity * * @return This buffer * * @throws IllegalArgumentException * If the preconditions on newLimit do not hold */ public final Buffer limit(int newLimit) {
if ((newLimit > capacity) || (newLimit < 0)) throw new IllegalArgumentException(); limit = newLimit; if (position > limit) position = limit; if (mark > limit) mark = -1; return this; }

标记(mark)

缓冲区中客户端指定的索引,通过调用mark()可以将标记设置为当前位置,调用reset()可以将当前位置设置为所标记的位置。

/**     * Sets this buffer's mark at its position.     *     * @return  This buffer     */    public final Buffer mark() {
mark = position; return this; } /** * Resets this buffer's position to the previously-marked position. * *

Invoking this method neither changes nor discards the mark's * value.

* * @return This buffer * * @throws InvalidMarkException * If the mark has not been set */ public final Buffer reset() {
int m = mark; if (m < 0) throw new InvalidMarkException(); position = m; return this; }

如果将位置设置为低于现有的标记,则丢弃这个标记。

与读取InputStream不同,读取缓冲区实际上不会以任何方式改变缓冲区中的数据,只可能向前或者向后设置位置,

Buffer主要方法

clear

clear()方法将位置设置为0,并将限度设置为容量,从而将缓冲区“清空”。这样一来,就可以完全重新填充缓冲区了。

/**     * Clears this buffer.  The position is set to zero, the limit is set to     * the capacity, and the mark is discarded.     *     * 

Invoke this method before using a sequence of channel-read or * put operations to fill this buffer. For example: * *

     * buf.clear();     // Prepare buffer for reading     * in.read(buf);    // Read data
* *

This method does not actually erase the data in the buffer, but it * is named as if it did because it will most often be used in situations * in which that might as well be the case.

* * @return This buffer */ public final Buffer clear() {
position = 0; limit = capacity; mark = -1; return this; }

clear()方法没有删除缓冲区中的老数据,这些数据仍然存在。

flip

flip()方法将限度设置为当前位置,位置设置为0。

/**     * Flips this buffer.  The limit is set to the current position and then     * the position is set to zero.  If the mark is defined then it is     * discarded.     *     * 

After a sequence of channel-read or put operations, invoke * this method to prepare for a sequence of channel-write or relative * get operations. For example: * *

     * buf.put(magic);    // Prepend header     * in.read(buf);      // Read data into rest of buffer     * buf.flip();        // Flip buffer     * out.write(buf);    // Write header + data to channel
* *

This method is often used in conjunction with the {@link * java.nio.ByteBuffer#compact compact} method when transferring data from * one place to another.

* * @return This buffer */ public final Buffer flip() {
limit = position; position = 0; mark = -1; return this; }

一般在操作完put方法之后,调用此方法来准备get,相反同样操作也可。

remaining

返回缓冲区中当前位置与限度之间的元素数。

/**     * Returns the number of elements between the current position and the     * limit.     *     * @return  The number of elements remaining in this buffer     */    public final int remaining() {
return limit - position; }

hasRemaining

如果缓冲区中还有数据就返回true。

/**     * Tells whether there are any elements between the current position and     * the limit.     *     * @return  true if, and only if, there is at least one element     *          remaining in this buffer     */    public final boolean hasRemaining() {
return position < limit; }

基本使用演示

public class Test {
public static void main(String[] args) {
ByteBuffer buffer = ByteBuffer.allocateDirect(1024); System.out.println("position: " + buffer.position() + ", limit: " + buffer.limit() + ", capacity: " + buffer.capacity()); System.out.println(); buffer.put("123456".getBytes()); System.out.println("====== 调用put '123456' ======"); System.out.println("position: " + buffer.position() + ", limit: " + buffer.limit() + ", capacity: " + buffer.capacity()); System.out.println(); int remaining = buffer.remaining(); System.out.println("======= 调用remaining方法之后 ======"); System.out.println("remaining: " + remaining); System.out.println(); buffer.flip(); System.out.println("======= 调用flip方法之后 ======"); System.out.println("position: " + buffer.position() + ", limit: " + buffer.limit() + ", capacity: " + buffer.capacity()); System.out.println(); remaining = buffer.remaining(); System.out.println("======= 调用remaining方法之后(注意观察flip之后,remaining的变化) ======"); System.out.println("remaining: " + remaining); System.out.println(); buffer.get(); System.out.println("======= 调用get方法之后 ======"); System.out.println("position: " + buffer.position() + ", limit: " + buffer.limit() + ", capacity: " + buffer.capacity()); System.out.println(); remaining = buffer.remaining(); System.out.println("======= 调用remaining方法之后 ======"); System.out.println("remaining: " + remaining); System.out.println(); buffer.clear(); System.out.println("======= 调用clear方法之后 ======"); System.out.println("position: " + buffer.position() + ", limit: " + buffer.limit() + ", capacity: " + buffer.capacity()); System.out.println(); remaining = buffer.remaining(); System.out.println("======= 调用remaining方法之后 (注意观察clear之后,remaining的变化)======"); System.out.println("remaining: " + remaining); }}
position: 0, limit: 1024, capacity: 1024====== 调用put '123456' ======position: 6, limit: 1024, capacity: 1024======= 调用remaining方法之后 ======remaining: 1018======= 调用flip方法之后 ======position: 0, limit: 6, capacity: 1024======= 调用remaining方法之后 ======remaining: 6======= 调用get方法之后 ======position: 1, limit: 6, capacity: 1024======= 调用remaining方法之后 ======remaining: 5======= 调用clear方法之后 ======position: 0, limit: 1024, capacity: 1024======= 调用remaining方法之后 ======remaining: 1024Process finished with exit code 0

转载地址:http://aolrb.baihongyu.com/

你可能感兴趣的文章
Sqoop往Hive导入数据实战
查看>>
Mysql到HBase的迁移
查看>>
Sqoop import进阶
查看>>
Hive语句是如何转化成MapReduce任务的
查看>>
Hive创建table报错:Permission denied: user=lenovo, access=WRITE, inode="":suh:supergroup:rwxr-xr-x
查看>>
Hive执行job时return code 2排查
查看>>
hive常用函数及数据结构介绍
查看>>
Hive面试题干货(亲自跟着做了好几遍,会了的话对面试大有好处)
查看>>
力扣题解-230. 二叉搜索树中第K小的元素(递归方法,中序遍历解决)
查看>>
力扣题解-123. 买卖股票的最佳时机 III(动态规划)
查看>>
Django 源码阅读:服务启动(wsgi)
查看>>
Django 源码阅读:url解析
查看>>
Docker面试题(一)
查看>>
第一轮面试题
查看>>
2020-11-18
查看>>
Docker面试题(二)
查看>>
一、redis面试题及答案
查看>>
消息队列2
查看>>
C++ 线程同步之临界区CRITICAL_SECTION
查看>>
测试—自定义消息处理
查看>>