Base128 基于Base64的变种编码

本文介绍了Base128,一个Base64的变种编码,适用于Stomp协议下的数据传输。由于Stomp对ASCII码0敏感,作者通过保留7位,确保每个字节的最后一位为1,从而减少了Base64编码中的位操作,提高了编码速度并减小了文件体积。Base128的实现避免了Base64中多余的位移和位或操作,简化了编码流程。
摘要由CSDN通过智能技术生成

Base128 基于Base64的变种编码

前言

毕设中的需求比较特殊,需要大量的用到长连接来进行数据传输,所以使用了Stomp来作为应用层协议。由于spring对其支持良好,服务端直接使用spring相关api完成编码。在spring中,其底层实现为WebSocket,可以简单理解为,在WebSocket的基础之上,对每一条消息封装一个包头(stomp协议)再进行传输,从而使消息的分发更加灵活,如订阅话题等等。这里不过多展开Stomp,但有一点是需要注意的是,Stomp是一个基于文本的协议,对二进制的传输不是特别友好。这主要是因为在Stomp中,使用ascii码0来代表一条消息的结束。这也就意味着,如果消息中包含ascii码0,这条消息是无法完成的进行解析的。然而比较尴尬的一点是,毕设里使用了一种二进制的对象序列化库(ProtocolBuffer),使得在进行消息传输之前,必须进行编码操作,所以今天来聊一聊编码优化的问题。

关于Base64

base64大家或多或少有些了解,这里希望详细分析下base64原理以及jdk1.8中对其提供的实现方式,同时解释下为什么这次没有使用Base64,而是写了一个听起来就很山寨的Base128…
base64经常用于解决网络数据传输的编码问题,要是有什么乱码的,发不过去数据的,拿base64一编码就老实了,听起来特别的高大上,其实原理简单到令人发指,了解过之后会有一种我上我也行的冲动。他主要是解决字符的转换问题,要知道,我们在屏幕上看到的每一个汉字、字母,其实都对应着一串数字,base64的工作就是把一串数字转变成另外一串数字,避开那些敏感的数字就可以了。
直接举个例子:比如我有三个数字

6 6 6

对应的二进制表示是

 00000110 | 00000110 | 00000110  //这里用竖线稍微隔了一下

也就是说 每个数字对应8个二进制位
然后,我们稍稍向右挪动下这几个竖线,让他们变成6个一组,于是就成了这样

000001 | 100000 | 011000 | 000110  //8个一组变6个一组所以多加了条竖线

把这四组直接当做4个数字,也就是每组数字高位补两个0就变成了这样

00000001 | 00100000 | 00011000 | 00000110  

再转回十进制看一下就是

1 32 24 6

这样base64的工作就完成大半了,有没有发现,经过编码后的每一个数字,都不可能超过64,因为他的高两位永远是0,所以,在最后,我们将每一个数字按照编码表对应成64种可打印字符,整个编码的核心工作就完成了。当然我举的例子比较理想,因为三个数字经过编码正好可以变成四个,如果不巧数字的个数不能被3整除,可能还要做一些补齐操作,但这不重要,如果你很好奇,随便百度下就好了。
由于经过base64的编码之后,所有的二进制数据不管是几都落到可打印字符区间了,这样就能直接在网络中放心传输了。只是数据的长度变长了,这个没办法,原本一个byte可以表示-128~127,现在每个byte的高两位都不能表示数据,相当于拿空间换值域,为了正常的传输不得不作出的妥协。其实这也是我想对其改进的原因,对我来说,可能这对空间浪费的有点多了,同时更长的编码长度意味着更多的赋值操作,在java上数组访问和赋值是非常慢的,我们应该尽量减少这种操作的发生,所以才有了Base128的想法。在讲Base64之前,我们先来分析下jdk中的Base64是如何实现的

java中的Base64

在解析源码之前,我想先说明下java中位操作的基本知识,不了解的话就很难看懂下面的代码。其实要了解的东西也不多,我们只要明确几个细节就好了

  • byte->int

    byte b = -128;
    int a = (int)b; //求a的二进制表示

    我们知道b的二进制表示为0x11111111 其符号位为1,将其强制转换为32位的int时,系统会将高位全部补1 转换后的值为
    0x11111111111111111111111111111111
    并不是我们想要的
    0x00000000000000000000000011111111
    所以如果想要达到我们想要的结果 需要将上述代码改为

byte b = -128;
int a = (int)(b & 0xff);    
  • 位或
    如果我们希望将两个byte合并为一个int,可以通过位移+位或的操作来完成,还是上面的例子,如果我们有两个byte b1=b2=-128,要将两个byte合并在一起,首先要将两个byte都变成这种形式
    b1: 0x00000000000000000000000011111111
    b2: 0x00000000000000000000000011111111
    接着我们对b2做左移操作 两个数将变成这样
    b1: 0x00000000000000000000000011111111
    b2: 0x00000000000000001111111100000000
    然后我们对两个数做位或操作,结果就变成了
    b0: 0x00000000000000001111111111111111
    可以理解为&#x

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值