二進(jìn)制輔助工具類 ByteBuffer

ByteBuffer

a simple binary data processing tool
一個(gè)簡單的二進(jìn)制處理類

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

在TCP長連接中解決粘包半包有用到漠烧,項(xiàng)目PackageMessage

一:故事

寫一個(gè)TCP長連接方案炉擅,遇到粘包分包問題价说,服務(wù)端于是用ByteArrayOutStream實(shí)現(xiàn)了遵堵,感覺太過于麻煩浑槽, 于是用java nio 的 ByteBuffer,但是不太靈活聋亡,最后用Netty的ByteBuf類壁顶,豁然開朗,盡然可以把代碼壓縮到這么少诺核,轉(zhuǎn)念一想抄肖,Android端怎么實(shí)現(xiàn)呢久信?畢竟引入Netty包太大,即使是部分代碼也很大漓摩。Nio的ByteBuffer呢裙士?遇見好用的自然看不上不太靈活的,于是寫了此類解決幌甘。

二:引入

目前將ByteBuffer和PackageMessage都放到了MiniTCPClient項(xiàng)目里潮售。

ByteBuffer源碼

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

三:功能介紹

Java Nio的ByteBuffer用起來不靈活(只說內(nèi)存中二進(jìn)制處理,MappedByteBuffer等不算),功能上也只是比Java Nio的ByteBuffer多了幾個(gè)锅风,正好我想用的就是多的這幾個(gè)酥诽,比如內(nèi)部數(shù)組是支持動(dòng)態(tài)擴(kuò)展的,默認(rèn)大小256皱埠,如果write超過容量會(huì)自動(dòng)擴(kuò)容肮帐。計(jì)算方法如下:

    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處理方式會(huì)把多個(gè)ByteBuf用list形式組織起來,每個(gè)ByteBuf都不會(huì)太大边器,Netty那套很值得學(xué)習(xí)训枢,我也只能學(xué)習(xí)皮毛而已。

我寫的這個(gè)ByteBuffer也支持銷毀已讀部分discardReadBytes()忘巧,獲取原始array()和獲取剩余可讀數(shù)據(jù)readableBytesArray()恒界,單獨(dú)讀寫int、byte或者long砚嘴,隨意移動(dòng)指針位置等十酣。
從數(shù)組拷貝上使用System.arraycopy(),效率比較有保證

四:簡單使用

ByteBuffer結(jié)構(gòu)
變量名 類型 說明
readerIndex Integer 指針位置际长,即將讀取的位置
writerIndex Integer 指針位置耸采,即將寫入的位置
data ByteArray 原始數(shù)據(jù)數(shù)組
創(chuàng)建ByteBuffer
    ByteBuffer buffer = ByteBuffer.newByteBuffer();
    ByteBuffer buffer = ByteBuffer.newByteBuffer(int capacity)

capacity參數(shù)指定初始數(shù)組大小,默認(rèn)為256.

方法
方法名 參數(shù)一 參數(shù)二 返回值 說明
newByteBuffer() ByteBuffer 創(chuàng)建新ByteBuffer工育,默認(rèn)大小256
newByteBuffer(int capacity) 默認(rèn)大小 ByteBuffer 創(chuàng)建新ByteBuffer虾宇,大小為capacity
capacity() int 返回當(dāng)前最大容量
array() ByteArray 獲取原始數(shù)組,包含所有部分
clear() ByteBuffer 清理指針標(biāo)記如绸,狀態(tài)為剛創(chuàng)建狀態(tài)嘱朽,但是data數(shù)據(jù)不變,新數(shù)組會(huì)覆蓋舊數(shù)據(jù)怔接,除了array()獲取原始數(shù)組外無法得到舊數(shù)據(jù)
discardReadBytes() void 刪除已讀部分燥翅,重新初始化數(shù)組
readerIndex(int position) 重置指針位置 ByteBuffer 如果大于寫入位置,則可讀位置重置為寫入位置蜕提,readableBytes()結(jié)果則為0
readerIndex() int 讀指針位置
writerIndex() int 寫指針位置
readableBytes() int 當(dāng)前可讀數(shù)據(jù)量,writerIndex - readerIndex
writableBytes() int 當(dāng)前可寫入數(shù)據(jù)量靶端,每次觸發(fā)擴(kuò)容后都不一樣
read() int 讀取數(shù)據(jù)到byte谎势,1 byte凛膏,從readIndex位置開始
readByte() byte 讀取數(shù)據(jù)到byte,1 byte脏榆,從readIndex位置開始
readInt() int 讀取integer值猖毫,讀4 byte轉(zhuǎn)換為integer,從readIndex位置開始
readBytes(byte[] bytes) int 讀取數(shù)據(jù)到bytes须喂,從readIndex位置開始
readBytes(ByteBuffer b) 待存入數(shù)據(jù)對(duì)象 int 讀取數(shù)據(jù)到另一個(gè)ByteBuffer吁断,讀取數(shù)量
writeByte(byte b) 待寫入數(shù)據(jù) ByteBuffer 寫入Byte數(shù)據(jù),1 byte
write(int b) 待寫入數(shù)據(jù) ByteBuffer 寫入int值的byte轉(zhuǎn)換結(jié)果坞生,即丟棄高位仔役,1 byte
writeInt(int b) 待寫入int值 ByteBuffer 寫入integer數(shù)據(jù),4 byte
writeBytes(byte[] b) 待寫入ByteArray ByteBuffer 寫入數(shù)組
writeBytes(byte[] b, int dataLength) 待寫入ByteArray 指定寫入長度 ByteBuffer 寫入數(shù)組,并指定寫入長度
writeBytes(ByteBuffer b) 待寫入ByteBuffer ByteBuffer 寫入一個(gè)ByteBuffer可讀數(shù)據(jù)
writeBytes(ByteBuffer b, int dataLength) 待寫入ByteBuffer 指定寫入長度 ByteBuffer 寫入一個(gè)ByteBuffer可讀數(shù)據(jù)的部分長度

五:原理解析

創(chuàng)建一個(gè)數(shù)組是己,通過讀寫index來表示當(dāng)前數(shù)組可操作區(qū)域又兵,不用多次創(chuàng)建新數(shù)組并拷貝了,雖然默認(rèn)數(shù)組可能會(huì)變得很大卒废,減少創(chuàng)建拷貝過程能提高性能沛厨,以空間換時(shí)間。另外數(shù)組一般不輕易超過4k吧摔认,都是碎片的小數(shù)據(jù)逆皮,用這種方案最合適,如果是大數(shù)據(jù)量参袱,那就沒有什么意義了电谣。

六:小期待

以下項(xiàng)目都是我圍繞遠(yuǎn)程控制寫的項(xiàng)目和子項(xiàng)目。都給star一遍吧蓖柔。??

項(xiàng)目(Github) 語言 其他地址 運(yùn)行環(huán)境 項(xiàng)目說明
RemoteDataControllerForWeb JavaScript 簡書 瀏覽器 遠(yuǎn)程數(shù)據(jù)調(diào)試控制臺(tái)Web端
RemoteDataControllerForAndroid Java 簡書 Android設(shè)備 遠(yuǎn)程數(shù)據(jù)調(diào)試Android端
RemoteDataControllerForServer Java 簡書 運(yùn)行Java的設(shè)備 遠(yuǎn)程數(shù)據(jù)調(diào)試Server端
MiniHttpClient Java 簡書 運(yùn)行Java的設(shè)備 精簡的HttpClient
MiniHttpServer Java 簡書 運(yùn)行Java的設(shè)備 支持部分Http協(xié)議的Server
MiniTCPClient Java 簡書 運(yùn)行Java的設(shè)備 TCP長連接庫辰企,支持粘包拆包處理
PackageMessage Java 簡書 運(yùn)行Java的設(shè)備 TCP粘包與半包解決方案
ByteBuffer Java 簡書 運(yùn)行Java的設(shè)備 二進(jìn)制處理工具類
DataTables.AltEditor JavaScript 簡書 瀏覽器 Web端表格編輯組件

我的小站:IT狗窩
技術(shù)聯(lián)系QQ:1264957104

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市况鸣,隨后出現(xiàn)的幾起案子牢贸,更是在濱河造成了極大的恐慌,老刑警劉巖镐捧,帶你破解...
    沈念sama閱讀 206,311評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件潜索,死亡現(xiàn)場離奇詭異,居然都是意外死亡懂酱,警方通過查閱死者的電腦和手機(jī)竹习,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,339評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來列牺,“玉大人整陌,你說我怎么就攤上這事。” “怎么了泌辫?”我有些...
    開封第一講書人閱讀 152,671評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵随夸,是天一觀的道長。 經(jīng)常有香客問我震放,道長宾毒,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,252評(píng)論 1 279
  • 正文 為了忘掉前任殿遂,我火速辦了婚禮诈铛,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘墨礁。我一直安慰自己幢竹,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,253評(píng)論 5 371
  • 文/花漫 我一把揭開白布饵溅。 她就那樣靜靜地躺著妨退,像睡著了一般。 火紅的嫁衣襯著肌膚如雪蜕企。 梳的紋絲不亂的頭發(fā)上咬荷,一...
    開封第一講書人閱讀 49,031評(píng)論 1 285
  • 那天,我揣著相機(jī)與錄音轻掩,去河邊找鬼幸乒。 笑死,一個(gè)胖子當(dāng)著我的面吹牛唇牧,可吹牛的內(nèi)容都是我干的罕扎。 我是一名探鬼主播,決...
    沈念sama閱讀 38,340評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼丐重,長吁一口氣:“原來是場噩夢啊……” “哼腔召!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起扮惦,我...
    開封第一講書人閱讀 36,973評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤臀蛛,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后崖蜜,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體浊仆,經(jīng)...
    沈念sama閱讀 43,466評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,937評(píng)論 2 323
  • 正文 我和宋清朗相戀三年豫领,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了抡柿。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,039評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡等恐,死狀恐怖洲劣,靈堂內(nèi)的尸體忽然破棺而出备蚓,到底是詐尸還是另有隱情,我是刑警寧澤闪檬,帶...
    沈念sama閱讀 33,701評(píng)論 4 323
  • 正文 年R本政府宣布星著,位于F島的核電站,受9級(jí)特大地震影響粗悯,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜同欠,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,254評(píng)論 3 307
  • 文/蒙蒙 一样傍、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧铺遂,春花似錦衫哥、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,259評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至粮坞,卻和暖如春蚊荣,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背莫杈。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評(píng)論 1 262
  • 我被黑心中介騙來泰國打工互例, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人筝闹。 一個(gè)月前我還...
    沈念sama閱讀 45,497評(píng)論 2 354
  • 正文 我出身青樓媳叨,卻偏偏與公主長得像,于是被迫代替她去往敵國和親关顷。 傳聞我的和親對(duì)象是個(gè)殘疾皇子糊秆,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,786評(píng)論 2 345