標籤:ring code ati 抽象 eof capacity written moved data-
Buffer是一個抽象類別,位於java.nio包中,主要用作緩衝區。注意:Buffer是非安全執行緒類。
緩衝區本質上是一塊可以寫入資料,然後可以從中讀取資料的記憶體。這塊記憶體被封裝成NIO Buffer對象,並提供了一組方法,用來方便的訪問該塊記憶體。
NIO 有以下幾種Buffer類型:
- ByteBuffer
- MappedByteBuffer
- CharBuffer
- DoubleBuffer
- FloatBuffer
- IntBuffer
- LongBuffer
- ShortBuffer
capacity
作為一個記憶體塊,Buffer有一個固定的大小值,也叫“capacity”.你只能往裡寫capacity個byte、long,char等類型。一旦Buffer滿了,需要將其清空(通過讀資料或者清除資料)才能繼續寫資料往裡寫資料。
capacity一旦初始化
後就不會改變,其值一直為常量。在使用中我們一般使用Buffer的抽象子類ByteBuffer.allocate()方法,實際上是產生ByteArrayBuffer類。
position
當你寫資料到Buffer中時,position表示當前的位置。初始的position值為0.當一個byte、long等資料寫到Buffer後, position會向前移動到下一個可插入資料的Buffer單元。position最大可為capacity – 1。
當讀取資料時,也是從某個特定位置讀。當將Buffer從寫入模式切換到讀模式,position會被重設為0。當從Buffer的position處讀取資料時,position向前移動到下一個可讀的位置。
limit
在讀模式下,Buffer的limit表示你最多能從Buffer裡讀多少資料。 寫入模式下,limit等於Buffer的capacity。
當切換Buffer到讀模式時, limit表示你最多能讀到多少資料。因此,當切換Buffer到讀模式時,limit會被設定成寫入模式下的position值。換句話說,你能讀到之前寫入的所有資料(limit被設定成已寫資料的數量,這個值在寫入模式下就是position)
(1)Buffer中定義的變數含義
/** * <code>UNSET_MARK</code> means the mark has not been set. */static final int UNSET_MARK = -1;/** * The capacity of this buffer, which never changes. */final int capacity;/** * <code>limit - 1</code> is the last element that can be read or written. * Limit must be no less than zero and no greater than <code>capacity</code>. */int limit;/** * Mark is where position will be set when <code>reset()</code> is called. * Mark is not set by default. Mark is always no less than zero and no * greater than <code>position</code>. */int mark = UNSET_MARK;/** * The current position of this buffer. Position is always no less than zero * and no greater than <code>limit</code>. */int position = 0;/** * The log base 2 of the element size of this buffer. Each typed subclass * (ByteBuffer, CharBuffer, etc.) is responsible for initializing this * value. The value is used by JNI code in frameworks/base/ to avoid the * need for costly ‘instanceof‘ tests. */final int _elementSizeShift;/** * For direct buffers, the effective address of the data; zero otherwise. * This is set in the constructor. */final long effectiveDirectAddress;
(2)clear()方法用於寫入模式,其作用為清空Buffer中的內容,所謂清空是指寫上限與Buffer的真實容量相同,即limit==capacity,同時將當前寫位置置為最前端下標為0處。代碼如下:
/** * <code>UNSET_MARK</code> means the mark has not been set. */static final int UNSET_MARK = -1;/** * Clears this buffer. * <p> * While the content of this buffer is not changed, the following internal * changes take place: the current position is reset back to the start of * the buffer, the value of the buffer limit is made equal to the capacity * and mark is cleared. * * @return this buffer. */public final Buffer clear() { position = 0; //設定當前下標為0 mark = UNSET_MARK; //取消標幟 limit = capacity; //設定寫越界位置與和Buffer容量相同 return this;}
(3)reset()方法和clear()方法一樣用於寫入模式,區別是reset()的作用是丟棄mark位置以後的資料,重新從mark位置開始寫入,且mark不能未設定;而clear是從0位置開始重新寫入。
(4)rewind()在讀寫入模式下都可用,它單純的將當前位置置0,同時取消mark標記,僅此而已;也就是說寫入模式下limit仍保持與Buffer容量相同,只是重頭寫而已;讀模式下limit仍然與rewind()調用之前相同,也就是為flip()調用之前寫入模式下的position的最後位置,flip()調用後此位置變為了讀模式的limit位置,即越界位置,代碼如下:
/** * Rewinds this buffer. * <p> * The position is set to zero, and the mark is cleared. The content of this * buffer is not changed. * * @return this buffer. */public final Buffer rewind() { position = 0; mark = UNSET_MARK; return this;}
(5)flip()函數的作用是將寫入模式轉變為讀模式,即將寫入模式下的Buffer中內容的最後位置變為讀模式下的limit位置,作為讀越界位置,同時將當前讀位置置為0,表示轉換後重頭開始讀,同時再消除寫入模式下的mark標記,代碼如下
/** * Flips this buffer. * <p> * The limit is set to the current position, then the position is set to * zero, and the mark is cleared. * <p> * The content of this buffer is not changed. * * @return this buffer. */public final Buffer flip() { limit = position; position = 0; mark = UNSET_MARK; return this;}
(6)remaining()僅在讀模式下使用,用來擷取還未讀出的位元組數。
(7)Buffer的抽象子類ByteBuffer的compact()方法也蠻重要的。compact()的作用是壓縮資料。比如當前EOF是6,當前指標指向2(即0,1的資料已經寫出了,沒用了),那麼compact方法將把2,3,4,5的資料挪到0,1,2,3的位置,然後指標指向4的位置。這樣的意思是,從4的位置接著再寫入資料。
/** * Compacts this byte buffer. * <p> * The remaining bytes will be moved to the head of the * buffer, starting from position zero. Then the position is set to * {@code remaining()}; the limit is set to capacity; the mark is * cleared. * * @return {@code this} * @throws ReadOnlyBufferException * if no changes may be made to the contents of this buffer. */public abstract ByteBuffer compact();
(8)equals()
當滿足下列條件時,表示兩個Buffer相等:
- 有相同的類型(byte、char、int等)。
- Buffer中剩餘的byte、char等的個數相等。
- Buffer中所有剩餘的byte、char等都相同。
equals只是比較Buffer的一部分,不是每一個在它裡面的元素都比較(即它只比較Buffer中的剩餘元素)。
以ByteBuffer為例
-
/** * Tells whether or not this buffer is equal to another object. * * <p> Two byte buffers are equal if, and only if, * * <ol> * * <li><p> They have the same element type, </p></li> * * <li><p> They have the same number of remaining elements, and * </p></li> * * <li><p> The two sequences of remaining elements, considered * independently of their starting positions, are pointwise equal. * </p></li> * * </ol> * * <p> A byte buffer is not equal to any other type of object. </p> * * @param ob The object to which this buffer is to be compared * * @return <tt>true</tt> if, and only if, this buffer is equal to the * given object */public boolean equals(Object ob) { if (this == ob) return true; if (!(ob instanceof ByteBuffer)) return false; ByteBuffer that = (ByteBuffer)ob; if (this.remaining() != that.remaining()) return false; int p = this.position(); for (int i = this.limit() - 1, j = that.limit() - 1; i >= p; i--, j--) if (!equals(this.get(i), that.get(j))) return false; return true;}
(9)compareTo()
compareTo()方法比較兩個Buffer的剩餘元素(byte、char等), 如果滿足下列條件,則認為一個Buffer“小於”另一個Buffer:
- 第一個不相等的元素小於另一個Buffer中對應的元素 。
- 所有元素都相等,但第一個Buffer比另一個先耗盡(第一個Buffer的元素個數比另一個少)。
以ByteBuffer為例
-
/** * Compares this buffer to another. * * <p> Two byte buffers are compared by comparing their sequences of * remaining elements lexicographically, without regard to the starting * position of each sequence within its corresponding buffer. * Pairs of {@code byte} elements are compared as if by invoking * {@link Byte#compare(byte,byte)}. * * <p> A byte buffer is not comparable to any other type of object. * * @return A negative integer, zero, or a positive integer as this buffer * is less than, equal to, or greater than the given buffer */public int compareTo(ByteBuffer that) { int n = this.position() + Math.min(this.remaining(), that.remaining()); for (int i = this.position(), j = that.position(); i < n; i++, j++) { int cmp = compare(this.get(i), that.get(j)); if (cmp != 0) return cmp; } return this.remaining() - that.remaining();}
補充:
轉載出處——http://blog.csdn.net/chy555chy/article
Java NIO —— Buffer(緩衝區)