Java-NIO:缓冲区(Buffer)的数据存取

Posted yy

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java-NIO:缓冲区(Buffer)的数据存取相关的知识,希望对你有一定的参考价值。

  • 缓冲区(Buffer):

  一个用于特定基本数据类行的容器。有java.nio包定义的,所有缓冲区都是抽象类Buffer的子类。

  Java NIO中的Buffer主要用于与NIO通道进行交互,数据是从通道读入到缓冲区,从缓冲区写入通道中的。

  Buffer就像一个数组,可以保存多个相同类型的数据。根据类型不同(boolean除外),有以下Buffer常用子类:

  1. ByteBuffer
  2. CharBuffer
  3. ShortBuffer
  4. IntBuffer
  5. LongBuffer
  6. FloatBuffer
  7. DoubleBuffer

上述Buffer类他们都采用相似的方法进行管理数据,只是各自管理的数据类型不同而已,都是通过以下方法获取一个Buffer对象:

static XxxBuffer allocate(int capacity)

创建一个容量为capacity的XxxBuffer对象。

  • Buffer中的重要概念:

1)容量(capacity):表示Buffer最大数据容量,缓冲区容量不能为负,并且建立后不能修改。

2)限制(limit):第一个不应该读取或者写入的数据的索引,即位于limit后的数据不可以读写。缓冲区的限制不能为负,并且不能大于其容量(capacity)。

3)位置(position):下一个要读取或写入的数据的索引。缓冲区的位置不能为负,并且不能大于其限制(limit)。

4)标记(mark)与重置(reset):标记是一个索引,通过Buffer中的mark()方法指定Buffer中一个特定的position,之后可以通过调用reset()方法恢复到这个position。

java.nio.Buffer.java
  1 /*
  2  * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
  3  * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  4  *
  5  *
  6  *
  7  *
  8  *
  9  *
 10  *
 11  *
 12  *
 13  *
 14  *
 15  *
 16  *
 17  *
 18  *
 19  *
 20  *
 21  *
 22  *
 23  *
 24  */
 25 
 26 package java.nio;
 27 
 28 import java.util.Spliterator;
 29 
 30 /**
 31  * A container for data of a specific primitive type.
 32  *
 33  * <p> A buffer is a linear, finite sequence of elements of a specific
 34  * primitive type.  Aside from its content, the essential properties of a
 35  * buffer are its capacity, limit, and position: </p>
 36  *
 37  * <blockquote>
 38  *
 39  *   <p> A buffer\'s <i>capacity</i> is the number of elements it contains.  The
 40  *   capacity of a buffer is never negative and never changes.  </p>
 41  *
 42  *   <p> A buffer\'s <i>limit</i> is the index of the first element that should
 43  *   not be read or written.  A buffer\'s limit is never negative and is never
 44  *   greater than its capacity.  </p>
 45  *
 46  *   <p> A buffer\'s <i>position</i> is the index of the next element to be
 47  *   read or written.  A buffer\'s position is never negative and is never
 48  *   greater than its limit.  </p>
 49  *
 50  * </blockquote>
 51  *
 52  * <p> There is one subclass of this class for each non-boolean primitive type.
 53  *
 54  *
 55  * <h2> Transferring data </h2>
 56  *
 57  * <p> Each subclass of this class defines two categories of <i>get</i> and
 58  * <i>put</i> operations: </p>
 59  *
 60  * <blockquote>
 61  *
 62  *   <p> <i>Relative</i> operations read or write one or more elements starting
 63  *   at the current position and then increment the position by the number of
 64  *   elements transferred.  If the requested transfer exceeds the limit then a
 65  *   relative <i>get</i> operation throws a {@link BufferUnderflowException}
 66  *   and a relative <i>put</i> operation throws a {@link
 67  *   BufferOverflowException}; in either case, no data is transferred.  </p>
 68  *
 69  *   <p> <i>Absolute</i> operations take an explicit element index and do not
 70  *   affect the position.  Absolute <i>get</i> and <i>put</i> operations throw
 71  *   an {@link IndexOutOfBoundsException} if the index argument exceeds the
 72  *   limit.  </p>
 73  *
 74  * </blockquote>
 75  *
 76  * <p> Data may also, of course, be transferred in to or out of a buffer by the
 77  * I/O operations of an appropriate channel, which are always relative to the
 78  * current position.
 79  *
 80  *
 81  * <h2> Marking and resetting </h2>
 82  *
 83  * <p> A buffer\'s <i>mark</i> is the index to which its position will be reset
 84  * when the {@link #reset reset} method is invoked.  The mark is not always
 85  * defined, but when it is defined it is never negative and is never greater
 86  * than the position.  If the mark is defined then it is discarded when the
 87  * position or the limit is adjusted to a value smaller than the mark.  If the
 88  * mark is not defined then invoking the {@link #reset reset} method causes an
 89  * {@link InvalidMarkException} to be thrown.
 90  *
 91  *
 92  * <h2> Invariants </h2>
 93  *
 94  * <p> The following invariant holds for the mark, position, limit, and
 95  * capacity values:
 96  *
 97  * <blockquote>
 98  *     <tt>0</tt> <tt>&lt;=</tt>
 99  *     <i>mark</i> <tt>&lt;=</tt>
100  *     <i>position</i> <tt>&lt;=</tt>
101  *     <i>limit</i> <tt>&lt;=</tt>
102  *     <i>capacity</i>
103  * </blockquote>
104  *
105  * <p> A newly-created buffer always has a position of zero and a mark that is
106  * undefined.  The initial limit may be zero, or it may be some other value
107  * that depends upon the type of the buffer and the manner in which it is
108  * constructed.  Each element of a newly-allocated buffer is initialized
109  * to zero.
110  *
111  *
112  * <h2> Clearing, flipping, and rewinding </h2>
113  *
114  * <p> In addition to methods for accessing the position, limit, and capacity
115  * values and for marking and resetting, this class also defines the following
116  * operations upon buffers:
117  *
118  * <ul>
119  *
120  *   <li><p> {@link #clear} makes a buffer ready for a new sequence of
121  *   channel-read or relative <i>put</i> operations: It sets the limit to the
122  *   capacity and the position to zero.  </p></li>
123  *
124  *   <li><p> {@link #flip} makes a buffer ready for a new sequence of
125  *   channel-write or relative <i>get</i> operations: It sets the limit to the
126  *   current position and then sets the position to zero.  </p></li>
127  *
128  *   <li><p> {@link #rewind} makes a buffer ready for re-reading the data that
129  *   it already contains: It leaves the limit unchanged and sets the position
130  *   to zero.  </p></li>
131  *
132  * </ul>
133  *
134  *
135  * <h2> Read-only buffers </h2>
136  *
137  * <p> Every buffer is readable, but not every buffer is writable.  The
138  * mutation methods of each buffer class are specified as <i>optional
139  * operations</i> that will throw a {@link ReadOnlyBufferException} when
140  * invoked upon a read-only buffer.  A read-only buffer does not allow its
141  * content to be changed, but its mark, position, and limit values are mutable.
142  * Whether or not a buffer is read-only may be determined by invoking its
143  * {@link #isReadOnly isReadOnly} method.
144  *
145  *
146  * <h2> Thread safety </h2>
147  *
148  * <p> Buffers are not safe for use by multiple concurrent threads.  If a
149  * buffer is to be used by more than one thread then access to the buffer
150  * should be controlled by appropriate synchronization.
151  *
152  *
153  * <h2> Invocation chaining </h2>
154  *
155  * <p> Methods in this class that do not otherwise have a value to return are
156  * specified to return the buffer upon which they are invoked.  This allows
157  * method invocations to be chained; for example, the sequence of statements
158  *
159  * <blockquote><pre>
160  * b.flip();
161  * b.position(23);
162  * b.limit(42);</pre></blockquote>
163  *
164  * can be replaced by the single, more compact statement
165  *
166  * <blockquote><pre>
167  * b.flip().position(23).limit(42);</pre></blockquote>
168  *
169  *
170  * @author Mark Reinhold
171  * @author JSR-51 Expert Group
172  * @since 1.4
173  */
174 
175 public abstract class Buffer {
176 
177     /**
178      * The characteristics of Spliterators that traverse and split elements
179      * maintained in Buffers.
180      */
181     static final int SPLITERATOR_CHARACTERISTICS =
182         Spliterator.SIZED | Spliterator.SUBSIZED | Spliterator.ORDERED;
183 
184     // Invariants: mark <= position <= limit <= capacity
185     private int mark = -1;
186     private int position = 0;
187     private int limit;
188     private int capacity;
189 
190     // Used only by direct buffers
191     // NOTE: hoisted here for speed in JNI GetDirectBufferAddress
192     long address;
193 
194     // Creates a new buffer with the given mark, position, limit, and capacity,
195     // after checking invariants.
196     //
197     Buffer(int mark, int pos, int lim, int cap) {       // package-private
198         if (cap < 0)
199             throw new IllegalArgumentException("Negative capacity: " + cap);
200         this.capacity = cap;
201         limit(lim);
202         position(pos);
203         if (mark >= 0) {
204             if (mark > pos)
205                 throw new IllegalArgumentException("mark > position: ("
206                                                    + mark + " > " + pos + ")");
207             this.mark = mark;
208         }
209     }
210 
211     /**
212      * Returns this buffer\'s capacity.
213      *
214      * @return  The capacity of this buffer
215      */
216     public final int capacity() {
217         return capacity;
218     }
219 
220     /**
221      * Returns this buffer\'s position.
222      *
223      * @return  The position of this buffer
224      */
225     public final int position() {
226         return position;
227     }
228 
229     /**
230      * Sets this buffer\'s position.  If the mark is defined and larger than the
231      * new position then it is discarded.
232      *
233      * @param  newPosition
234      *         The new position value; must be non-negative
235      *         and no larger than the current limit
236      *
237      * @return  This buffer
238      *
239      * @throws  IllegalArgumentException
240      *          If the preconditions on <tt>newPosition</tt> do not hold
241      */
242     public final Buffer position(int newPosition) {
243         if ((newPosition > limit) || (newPosition < 0))
244             throw new IllegalArgumentException();
245         position = newPosition;
246         if (mark > position) mark = -1;
247         return this;
248     }
249 
250     /**
251      * Returns this buffer\'s limit.
252      *
253      * @return  The limit of this buffer
254      */
255     public final int limit() {
256         return limit;
257     }
258 
259     /**
260      * Sets this buffer\'s limit.  If the position is larger than the new limit
261      * then it is set to the new limit.  If the mark is defined and larger than
262      * the new limit then it is discarded.
263      *
264      * @param  newLimit
265      *         The new limit value; must be non-negative
266      *         and no larger than this buffer\'s capacity
267      *
268      * @return  This buffer
269      *
270      * @throws  IllegalArgumentException
271      *          If the preconditions on <tt>newLimit</tt> do not hold
272      */
273     public final Buffer limit(int newLimit) {
274         if ((newLimit > capacity) || (newLimit < 0))
275             throw new IllegalArgumentException();
276         limit = newLimit;
277         if (position > limit) position = limit;
278         if (mark > limit) mark = -1;
279         return this;
280     }
281 
282     /**
283      * Sets this buffer\'s mark at its position.
284      *
285      * @return  This buffer
286      */
287     public final Buffer mark() {
288         mark = position;
289         return this;
290     }
291 
292     /**
293      * Resets this buffer\'s position to the previously-marked position.
294      *
295      * <p> Invoking this method neither changes nor discards the mark\'s
296      * value. </p>
297      *
298      * @return  This buffer
299      *
300      * @throws  InvalidMarkException
301      *          If the mark has not been set
302      */
303     public final Buffer reset() {
304         int m = mark;
305         if (m < 0)
306             throw new InvalidMarkException();
307         position = m;
308         return this;
309     }
310 
311     /**
312      * Clears this buffer.  The position is set to zero, the limit is set to
313      * the capacity, and the mark is discarded.
314      *
315      * <p> Invoke this method before using a sequence of channel-read or
316      * <i>put</i> operations to fill this buffer.  For example:
317      *
318      * <blockquote><pre>
319      * buf.clear();     // Prepare buffer for reading
320      * in.read(buf);    // Read data</pre></blockquote>
321      *
322      * <p> This method does not actually erase the data in the buffer, but it
323      * is named as if it did because it will most often be used in situations
324      * in which that might as well be the case. </p>
325      *
326      * @return  This buffer
327      */
328     public final Buffer clear() {
329         position = 0;
330         limit = capacity;
331         mark = -1;
332         return this;
333     }
334 
335     /**
336      * Flips this buffer.  The limit is set to the current position and then
337      * the position is set to zero.  If the mark is defined then it is
338      * discarded.
339      *
340      * <p> After a sequence of channel-read or <i>put</i> operations, invoke
341      * this method to prepare for a sequence of channel-write or relative
342      * <i>get</i> operations.  For example:
343      *
344      * <blockquote><pre>
345      * buf.put(magic);    // Prepend header
346      * in.read(buf);      // Read data into rest of buffer
347      * buf.flip();        // Flip buffer
348      * out.write(buf);    // Write header + data to channel</pre></blockquote>
349      *
350      * <p> This method is often used in conjunction with the {@link
351      * java.nio.ByteBuffer#compact compact} method when transferring data from
352      * one place to another.  </p>
353      *
354      * @return  This buffer
355      */
356     public final Buffer flip() {
357         limit = position;
358         position = 0;
359         mark = -1;
360         return this;
361     }
362 
363     /**
364      * Rewinds this buffer.  The position is set to zero and the mark is
365      * discarded.
366      *
367      * <p> Invoke this method before a sequence of channel-write or <i>get</i>
368      * operations, assuming that the limit has already been set
369      * appropriately.  For example:
370      *
371      * <blockquote><pre>
372      * out.write(buf);    // Write remaining data
373      * buf.rewind();      // Rewind buffer
374      * buf.get(array);    // Copy data into array</pre></blockquote>
375      *
376      * @return  This buffer
377      */
378     public final Buffer rewind() {
379         position = 0;
380         mark = -1;
381         return this;
382     }
383 
384     /**
385      * Returns the number of elements between the current position and the
386      * limit.
387      *
388      * @return  The number of elements remaining in this buffer
389      */
390     public final int remaining() {
391         return limit - position;
392     }
393 
394     /**
395      * Tells whether there are any elements between the current position and
396      * the limit.
397      *
398      * @return  <tt>true</tt> if, and only if, there is at least one element
399      *          remaining in this buffer
400      */
401     public final boolean hasRemaining() {
402         return position < limit;
403     }
404 
405     /**
406      * Tells whether or not this buffer is read-only.
407      *
408      * @return  <tt>true</tt> if, and only if, this buffer is read-only
409      */
410     public abstract boolean isReadOnly();
411 
412     /**
413      * Tells whether or not this buffer is backed by an accessible
414      * array.
415      *
416      * <p> If this method returns <tt>true</tt> then the {@link #array() array}
417      * and {@link #arrayOffset() arrayOffset} methods may safely be invoked.
418      * </p>
419      *
4

以上是关于Java-NIO:缓冲区(Buffer)的数据存取的主要内容,如果未能解决你的问题,请参考以下文章

缓冲区(Buffer)的数据存取

NIO之缓冲区(Buffer)的数据存取

Buffer的数据存取

Java NIO -- 缓冲区(Buffer)的数据存取

Java-NIO:通道(Channel)的原理与获取

Java-NIO:Channel聚集(gather)写入与分散(scatter)读取