二进制辅助工具类 ByteBuffer

ByteBuffer

a simple binary data processing tool
一个简单的二进制处理类

Github地址:https://github.com/itgowo/MiniTCPClient/blob/master/src/main/java/com/itgowo/tcp/me/ByteBuffer.java

在TCP长连接中解决粘包半包有用到,项目PackageMessage

一:故事

写一个TCP长连接方案,遇到粘包分包问题,服务端于是用ByteArrayOutStream实现了,感觉太过于麻烦, 于是用java nio 的 ByteBuffer,但是不太灵活,最后用Netty的ByteBuf类,豁然开朗,尽然可以把代码压缩到这么少,转念一想,Android端怎么实现呢?毕竟引入Netty包太大,即使是部分代码也很大。Nio的ByteBuffer呢?遇见好用的自然看不上不太灵活的,于是写了此类解决。

二:引入

目前将ByteBuffer和PackageMessage都放到了MiniTCPClient项目里。

ByteBuffer源码

compile 'com.itgowo:MiniTCPClient:最新版本

三:功能介绍

Java Nio的ByteBuffer用起来不灵活(只说内存中二进制处理,MappedByteBuffer等不算),功能上也只是比Java Nio的ByteBuffer多了几个,正好我想用的就是多的这几个,比如内部数组是支持动态扩展的,默认大小256,如果write超过容量会自动扩容。计算方法如下:

    private void autoExpandCapacity(int addLength) {
        if (writableBytes() < addLength) {
            int newSize = writableBytes() + addLength;
            int size = 0;
            while (size < newSize) {
                size += BUFFER_SIZE;
            }
            byte[] newBytes = new byte[size];
            writeBytesToBytes(data, newBytes, 0);
            data = newBytes;
        }
    }

Netty的CompositeByteBuf处理方式会把多个ByteBuf用list形式组织起来,每个ByteBuf都不会太大,Netty那套很值得学习,我也只能学习皮毛而已。

我写的这个ByteBuffer也支持销毁已读部分discardReadBytes(),获取原始array()和获取剩余可读数据readableBytesArray(),单独读写int、byte或者long,随意移动指针位置等。
从数组拷贝上使用System.arraycopy(),效率比较有保证

四:简单使用

ByteBuffer结构
变量名 类型 说明
readerIndex Integer 指针位置,即将读取的位置
writerIndex Integer 指针位置,即将写入的位置
data ByteArray 原始数据数组
创建ByteBuffer
    ByteBuffer buffer = ByteBuffer.newByteBuffer();
    ByteBuffer buffer = ByteBuffer.newByteBuffer(int capacity)

capacity参数指定初始数组大小,默认为256.

方法
方法名 参数一 参数二 返回值 说明
newByteBuffer() ByteBuffer 创建新ByteBuffer,默认大小256
newByteBuffer(int capacity) 默认大小 ByteBuffer 创建新ByteBuffer,大小为capacity
capacity() int 返回当前最大容量
array() ByteArray 获取原始数组,包含所有部分
clear() ByteBuffer 清理指针标记,状态为刚创建状态,但是data数据不变,新数组会覆盖旧数据,除了array()获取原始数组外无法得到旧数据
discardReadBytes() void 删除已读部分,重新初始化数组
readerIndex(int position) 重置指针位置 ByteBuffer 如果大于写入位置,则可读位置重置为写入位置,readableBytes()结果则为0
readerIndex() int 读指针位置
writerIndex() int 写指针位置
readableBytes() int 当前可读数据量,writerIndex - readerIndex
writableBytes() int 当前可写入数据量,每次触发扩容后都不一样
read() int 读取数据到byte,1 byte,从readIndex位置开始
readByte() byte 读取数据到byte,1 byte,从readIndex位置开始
readInt() int 读取integer值,读4 byte转换为integer,从readIndex位置开始
readBytes(byte[] bytes) int 读取数据到bytes,从readIndex位置开始
readBytes(ByteBuffer b) 待存入数据对象 int 读取数据到另一个ByteBuffer,读取数量
writeByte(byte b) 待写入数据 ByteBuffer 写入Byte数据,1 byte
write(int b) 待写入数据 ByteBuffer 写入int值的byte转换结果,即丢弃高位,1 byte
writeInt(int b) 待写入int值 ByteBuffer 写入integer数据,4 byte
writeBytes(byte[] b) 待写入ByteArray ByteBuffer 写入数组
writeBytes(byte[] b, int dataLength) 待写入ByteArray 指定写入长度 ByteBuffer 写入数组,并指定写入长度
writeBytes(ByteBuffer b) 待写入ByteBuffer ByteBuffer 写入一个ByteBuffer可读数据
writeBytes(ByteBuffer b, int dataLength) 待写入ByteBuffer 指定写入长度 ByteBuffer 写入一个ByteBuffer可读数据的部分长度

五:原理解析

创建一个数组,通过读写index来表示当前数组可操作区域,不用多次创建新数组并拷贝了,虽然默认数组可能会变得很大,减少创建拷贝过程能提高性能,以空间换时间。另外数组一般不轻易超过4k吧,都是碎片的小数据,用这种方案最合适,如果是大数据量,那就没有什么意义了。

六:小期待

以下项目都是我围绕远程控制写的项目和子项目。都给star一遍吧。😍

项目(Github) 语言 其他地址 运行环境 项目说明
RemoteDataControllerForWeb JavaScript 简书 浏览器 远程数据调试控制台Web端
RemoteDataControllerForAndroid Java 简书 Android设备 远程数据调试Android端
RemoteDataControllerForServer Java 简书 运行Java的设备 远程数据调试Server端
MiniHttpClient Java 简书 运行Java的设备 精简的HttpClient
MiniHttpServer Java 简书 运行Java的设备 支持部分Http协议的Server
MiniTCPClient Java 简书 运行Java的设备 TCP长连接库,支持粘包拆包处理
PackageMessage Java 简书 运行Java的设备 TCP粘包与半包解决方案
ByteBuffer Java 简书 运行Java的设备 二进制处理工具类
DataTables.AltEditor JavaScript 简书 浏览器 Web端表格编辑组件

我的小站:IT狗窝
技术联系QQ:1264957104

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,937评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,503评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,712评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,668评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,677评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,601评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,975评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,637评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,881评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,621评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,710评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,387评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,971评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,947评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,189评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,805评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,449评论 2 342