本文共 8131 字,大约阅读时间需要 27 分钟。
在JDK NIO的模型中,所有的I/O都要缓冲,不再向输出流写入数据和从输入流读取数据,而是要从缓冲区中读写数据,像在缓冲流中一样,缓冲区可能就是字节数组。
Java的所有基本数据类型都有特定的Buffer子类:ByteBuffer、CharBuffer、ShortBuffer、IntBuffer、LongBuffer、FloatBuffer、DoubleBuffer。不过在网络编程中几乎只会使用ByteBuffer。
位置(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不同,读取缓冲区实际上不会以任何方式改变缓冲区中的数据,只可能向前或者向后设置位置,
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 dataThis 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 channelThis 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/