Jetty源碼-IO-BufferUtil

    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------------------------------------------工具

相關文章
相關標籤/搜索