文档章节

Jetty源码-IO-BufferUtil

robin-yao
 robin-yao
发布于 2015/04/16 23:33
字数 837
阅读 562
收藏 29

    jetty 源码 BufferUtil 工具类主要是封装了对JDK ByteBuffer的操作。通过BufferUtil可以更容易的操作ByteBuffer.

由于ByteBuffer分为fill模式即写模式、flush模式即读模式,我们经常会在读写之间把ByteBuffer的状态搞混,经常忘记调用flip()等等,而且代码不容易理解。以后我们可以把jetty提供的BufferUitl引入作为工具类,很方便的操作ByteBuffer。如下示例:

 //置为写模式
  int pos = BufferUtil.flipToFill(buffer);
  try
  {        //写入数据
          buffer.put(data);
  }
  finally
  {        //置为读模式
          flipToFlush(buffer, pos);
  }

下面是贴出的部分BufferUitl代码,及个人的注释:

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  

END------------------------------------------

© 著作权归作者所有

共有 人打赏支持
robin-yao
粉丝 152
博文 54
码字总数 61496
作品 0
杭州
Jetty 7.6.0.RC0 and 8.1.0RC0

Jetty 的 7.6.0 和 8.1.0 的候选发行版本可从下面地址获取: http://eclipse.org/jetty http://jetty.codehaus.org 详细改进记录: jetty-8.1.0.RC0 - 30 November 2011 + 352565 cookie htt......

红薯
2011/12/01
767
1
Jetty 9.0.4 发布,支持 Servlet 3.1 非堵塞 I/O

Jetty 发布 9.0.4 更新版本,相关链接: Distributions: http://download.eclipse.org/jetty/stable-9/dist/ Documentation: http://www.eclipse.org/jetty/documentation/current/ Javadoc......

oschina
2013/06/27
3.8K
5
Jetty 9.2.10.v20150310/Jetty 9.3.0.M2 发布

Jetty 9.2.10.v20150310 发布,此版本是个维护版本,主要是 jetty-proxy 和 jetty-client 方面的 bug 修复。 更新日志: Â+ 445518 Provide different error callbacks to ProxyServlet. Â...

oschina
2015/03/18
2.6K
1
node npm install 报错

E:angularJs2angular2-seed-master>npm install > bufferutil@1.2.1 install E:angularJs2angular2-seed-masternode_modulesbufferutil > node-gyp rebuild E:angularJs2angular2-seed-maste......

guo_sunshine
2016/03/16
1K
0
eclipse使用maven tomcat插件部署无法关联源代码

eclipse maven 起服务debug无法关联源码 博客分类: maven eclipse 1. 安装sourcelookup插件: update site: 1) http://bjmi.github.io/update-site/ (3.8.2可用,后续描述均针对此插件) 2) ht...

赵作文
2015/10/20
246
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

文件的压缩与解压(linux)

Linux下*.tar.gz文件解压缩命令 1.压缩命令:   命令格式:tar -zcvf 压缩后文件名.tar.gz 被压缩文件名 可先切换到当前目录下。压缩文件名和被压缩文件名都可加入路径。 2.解压缩命令: ...

qimh
29分钟前
1
0
invalid character found in the request target 异常

这个异常时因为Tomcat 9不支持请求格式出现“{”等非法字符的问题 因为tomcat版本问题遇到的坑,记录一下。 问题 今天由于要测试一下订单详情页的异步查询,在本地起了一个服务,发送的请求是...

edwardGe
34分钟前
3
0
发现抓包软件fiddler的bug

1个请求他跳转之后,直接400,被拦在了Apache,使用fiddler 的,replay requests 是同样的结果,但是replay composer确是正常的。 也就是说这replay requests 是发原来的包,replay composer...

NLGBZJ
44分钟前
1
0
linux screen 命令详解

shell关闭后, 主机仍然运行 screen命令 启动jenkins以后, screen, 然后按ctrl+a 再按d 这样暂停了子界面, 这时候回到了父界面 用screen –ls查看目前子界面的状态 [root@free /]# screen -l...

SuShine
45分钟前
2
0
mac机器切换无线网络导致网页不能打开的问题

问题: 公司和家里使用不同的WI-FI,每次从家到公司时自动切换网络后,公司的许多地址不能访问, ping域名是可以ping同的,但是网页却打不开... 问题分析: 初步猜想是DNS缓存的问题? 对于MAC系统没...

Lennie002
47分钟前
1
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部