jetty 源碼 BufferUtil 工具類主要是封裝了對JDK ByteBuffer的操做。經過BufferUtil能夠更容易的操做ByteBuffer.
java
因爲ByteBuffer分爲fill模式即寫模式、flush模式即讀模式,咱們常常會在讀寫之間把ByteBuffer的狀態搞混,常常忘記調用flip()等等,並且代碼不容易理解。之後咱們能夠把jetty提供的BufferUitl引入做爲工具類,很方便的操做ByteBuffer。以下示例:數組
//置爲寫模式 int pos = BufferUtil.flipToFill(buffer); try { //寫入數據 buffer.put(data); } finally { //置爲讀模式 flipToFlush(buffer, pos); }
下面是貼出的部分BufferUitl代碼,及我的的註釋:app
public class BufferUtil { /** * 分配flush模式的ByteBuffer,limit和position都爲0,在寫入數據時,必須先翻爲fill模式 * @param capacity * @return */ public static ByteBuffer allocate(int capacity) { ByteBuffer buf = ByteBuffer.allocate(capacity); buf.limit(0); return buf; } public static ByteBuffer allocateDirect(int capacity) { ByteBuffer buf = ByteBuffer.allocateDirect(capacity); buf.limit(0); return buf; } /** * 清空buffer ,只需把positoin 和limit 同時置爲0 * @param buffer */ public static void clear(ByteBuffer buffer) { if (buffer != null) { buffer.position(0); buffer.limit(0); } } /** * 清空buffer ,置爲fill模式 * @param buffer */ public static void clearToFill(ByteBuffer buffer) { if (buffer != null) { buffer.position(0); buffer.limit(buffer.capacity()); } } /** * 翻轉爲fill模式 * @param buffer * @return */ public static int flipToFill(ByteBuffer buffer) { int position = buffer.position(); int limit = buffer.limit(); //說明正好flush完,能夠徹底轉換未fill模式 if (position == limit) { buffer.position(0); buffer.limit(buffer.capacity()); return 0; } //當前limit equal capacity,另申請空間 int capacity = buffer.capacity(); if (limit == capacity) { buffer.compact(); return 0; } //通常狀況,剩餘的容量,可寫的空間 buffer.position(limit); buffer.limit(capacity); return position; } /** * 轉爲flush模式,即讀模式,把當前寫到的位置至爲limit,動態傳入讀開始位置position, * 若是position未0 ,該方法的做用和 ByteBuffer.flip()的做用等價 * @param buffer * @param position */ public static void flipToFlush(ByteBuffer buffer, int position) { buffer.limit(buffer.position()); buffer.position(position); } /** * 把buffer轉換爲數組。 * @param buffer * @return */ public static byte[] toArray(ByteBuffer buffer) { //主要針對heap buffer if (buffer.hasArray()) { byte[] array = buffer.array(); int from=buffer.arrayOffset() + buffer.position(); return Arrays.copyOfRange(array, from, from + buffer.remaining()); } //針對 direct buffer else { byte[] to = new byte[buffer.remaining()]; buffer.slice().get(to); return to; } } /** * 是否爲空 ,remaining() 主要是 limit - position * @param buf * @return */ public static boolean isEmpty(ByteBuffer buf) { return buf == null || buf.remaining() == 0; } public static boolean hasContent(ByteBuffer buf) { return buf != null && buf.remaining() > 0; } public static boolean isFull(ByteBuffer buf) { return buf != null && buf.limit() == buf.capacity(); } public static int length(ByteBuffer buffer) { return buffer == null ? 0 : buffer.remaining(); } public static int space(ByteBuffer buffer) { if (buffer == null) return 0; return buffer.capacity() - buffer.limit(); } public static boolean compact(ByteBuffer buffer) { if (buffer.position()==0) return false; boolean full = buffer.limit() == buffer.capacity(); buffer.compact().flip(); return full && buffer.limit() < buffer.capacity(); } /** * 把from中未讀的,寫到 to 中 * @param from Buffer 讀模式 flush * @param to Buffer 寫模式 fill * @return number of bytes moved */ public static int put(ByteBuffer from, ByteBuffer to) { int put; int remaining = from.remaining(); if (remaining > 0) { //若是空間足夠,直接寫入 if (remaining <= to.remaining()) { to.put(from); put = remaining; //把from 讀完 from.position(from.limit()); } //heap buffer else if (from.hasArray()) { put = to.remaining(); //只讀部分數據 to.put(from.array(), from.arrayOffset() + from.position(), put); from.position(from.position() + put); } //direct buffer else { //只讀部分數據 put = to.remaining(); ByteBuffer slice = from.slice(); slice.limit(put); to.put(slice); from.position(from.position() + put); } } else put = 0; return put; } /** 添加 byte[] 到buffer中 * @param to * @param b * @param off * @param len * @throws java.nio.BufferOverflowException */ public static void append(ByteBuffer to, byte[] b, int off, int len) throws BufferOverflowException { //置爲寫模式 int pos = flipToFill(to); try { to.put(b, off, len); } finally { //置爲讀模式 flipToFlush(to, pos); } } /** * 從文件中讀數據到buffer中 * @param file * @param buffer * @throws IOException */ public static void readFrom(File file, ByteBuffer buffer) throws IOException { try(RandomAccessFile raf = new RandomAccessFile(file,"r")) { FileChannel channel = raf.getChannel(); long needed=raf.length(); while (needed>0 && buffer.hasRemaining()) needed=needed-channel.read(buffer); } } public static void readFrom(InputStream is, int needed, ByteBuffer buffer) throws IOException { ByteBuffer tmp = allocate(8192); while (needed > 0 && buffer.hasRemaining()) { int l = is.read(tmp.array(), 0, 8192); if (l < 0) break; tmp.position(0); tmp.limit(l); buffer.put(tmp); } } }
轉載請代表來源:http://my.oschina.net/robinyao/blog/402692 dom
END------------------------------------------工具