JDK NIO包中Buffer基本使用

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 <tt>newPosition</tt> 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 <tt>newLimit</tt> 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.
     *
     * <p> Invoking this method neither changes nor discards the mark's
     * value. </p>
     *
     * @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.
     *
     * <p> Invoke this method before using a sequence of channel-read or
     * <i>put</i> operations to fill this buffer.  For example:
     *
     * <blockquote><pre>
     * buf.clear();     // Prepare buffer for reading
     * in.read(buf);    // Read data</pre></blockquote>
     *
     * <p> 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. </p>
     *
     * @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.
     *
     * <p> After a sequence of channel-read or <i>put</i> operations, invoke
     * this method to prepare for a sequence of channel-write or relative
     * <i>get</i> operations.  For example:
     *
     * <blockquote><pre>
     * 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</pre></blockquote>
     *
     * <p> This method is often used in conjunction with the {@link
     * java.nio.ByteBuffer#compact compact} method when transferring data from
     * one place to another.  </p>
     *
     * @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  <tt>true</tt> 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: 1024

Process finished with exit code 0
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

码拉松

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

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

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

打赏作者

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

抵扣说明:

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

余额充值