注意java6幫助文檔對compact方法的介紹
compact
public abstract ByteBuffer compact()壓縮此緩衝區(可選操作)。
將緩衝區的<strong><em><u>當前位置和界限之間的字節(如果有)</u></em></strong>複製到緩衝區的開始處。即將索引 p = position() 處的字節複製到索引 0 處,將索引 p + 1 處的字節複製到索引 1 處,依此類推,直到將索引 limit() - 1 處的字節複製到索引 n = limit() - 1 - p 處。然後將緩衝區的位置設置爲 n+1,並將其界限設置爲其容量。如果已定義了標記,則丟棄它。
將緩衝區的位置設置爲複製的字節數,而不是零,以便調用此方法後可以緊接着調用另一個相對 put 方法。
從緩衝區寫入數據之後調用此方法,以防寫入不完整。例如,以下循環語句通過 buf 緩衝區將字節從一個信道複製到另一個信道:
buf.clear(); // Prepare buffer for use
while (in.read(buf) >= 0 || buf.position != 0) {
buf.flip();
out.write(buf);
buf.compact(); // In case of partial write
}
返回:
此緩衝區
拋出:
ReadOnlyBufferException - 如果此緩衝區是隻讀緩衝區
上文中的加黑加粗斜體部分表明了,爲什麼compact通常與flip方法合用:在通道(channel)間進行復制的時候,我們知道put或者get方法會通過標記pos的位置來標記字符位置,
flip在限制limit後,調用put方法(如上文中的例子),此時我們調用compact方法會執行兩個動作,1、清除之前已經寫如果的字符;2、根據上文加黑加粗斜體部分表明pos的位置將在0,通過這兩步達到我們的預期,這就是爲什麼此時單純的調用filp方法不行的原因。
下面通過兩個圖片形象說明compact的動作:
執行compact之前緩衝區在內存中的表現:
compact後緩衝區的表現:
由上圖可看:分爲兩點:
1、釋放一部分數據,即pos所指位置前移至零處;
2、重新填充,如果要重新填衝,pos的位置要慎重,這就是爲什麼最後pos的位置在4的原因
經過這兩步之後形成所謂的壓縮
下面再給出通道間複製字符串的代碼:
package com.z;
import java.nio.ByteBuffer;
import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel;
import java.nio.channels.WritableByteChannel;
public class ChannelCopy {
public static void main(String[] args) throws Exception{
ReadableByteChannel src = Channels.newChannel(System.in);
WritableByteChannel des = Channels.newChannel(System.out);
copy1(src,des);
src.close();
des.close();
}
private static void copy1(ReadableByteChannel src, WritableByteChannel des) throws Exception{
ByteBuffer tmp = ByteBuffer.allocate(16 * 1024);
while(src.read(tmp) != -1){
tmp.flip();
des.write(tmp);
tmp.compact();
}
tmp.flip();
while(tmp.hasRemaining()){
des.write(tmp);
}
}
}