马上:纸币互动,智能笔数据点压缩

17 篇文章 0 订阅
13 篇文章 0 订阅

马上:纸币互动,智能笔数据点压缩

对接一款智能笔,笔的数据是通过蓝牙传给app, 但是笔的笔迹点数量很多,网络传输用json就不恰当。所以一番调研才起二进制压缩点(数字压缩基本原理)

基本数据

class Dot implements Serializable {
    public int Counter;
    public int SectionID;
    public int OwnerID;
    public int BookID;
    public int PageID;
    public long timelong;
    public int x;
    public int y;
    public int fx;
    public int fy;
    public int force;
    public int angle;
    public Dot.DotType type;
    public float ab_x;
    public float ab_y;
    public int color = -16777216;
 }

上面除了timelong, 其它数据都可以通过一个字节来装载

Dot vPenDot = list.get(i);
int index = i * DOT_BYTE_LENGTH;
bytes[index] = (byte) vPenDot.Counter;
bytes[index + 1] = (byte) vPenDot.BookID;
bytes[index + 2] = (byte) vPenDot.SectionID;
bytes[index + 3] = (byte) vPenDot.OwnerID;
bytes[index + 4] = (byte) vPenDot.angle;
bytes[index + 5] = (byte) vPenDot.force;
bytes[index + 6] = (byte) vPenDot.x;
bytes[index + 7] = (byte) vPenDot.y;
bytes[index + 8] = (byte) vPenDot.fx;
bytes[index + 9] = (byte) vPenDot.fy;
//枚举类转为数字存储
bytes[index + 10] = (byte) vPenDot.type.ordinal();

同样long型用8个字节存储. 要用byte 来装的话

long timeLong = vPenDot.timelong;
//直接赋值
bytes[index + 11] = (byte) (timeLong >> 56);
bytes[index + 12] = (byte) (timeLong >> 48);
bytes[index + 13] = (byte) (timeLong >> 40);
bytes[index + 14] = (byte) (timeLong >> 32);
bytes[index + 15] = (byte) (timeLong >> 24);
bytes[index + 16] = (byte) (timeLong >> 16);
bytes[index + 17] = (byte) (timeLong >> 8);
bytes[index + 18] = (byte) timeLong;

同样还原数据点,就反之

Dot dot = new Dot();
dot.Counter = (dotsBytes[index] & FF);
dot.BookID = (dotsBytes[index + 1] & FF);
dot.PageID = (dotsBytes[index + 2] & FF);
dot.SectionID = (dotsBytes[index + 3] & FF);
dot.OwnerID = (dotsBytes[index + 4] & FF);
dot.angle = (dotsBytes[index + 5] & FF);
dot.force = (dotsBytes[index + 6] & FF);
dot.x = (dotsBytes[index + 7] & FF);
dot.y = (dotsBytes[index + 8] & FF);
dot.fx = (dotsBytes[index + 9] & FF);
dot.fy = (dotsBytes[index + 10] & FF);
dot.type = (getType(dotsBytes[index + 11] & FF));
dot.ab_x = (Dot.toAbsolute(dot.x, dot.fx));
dot.ab_y = Dot.toAbsolute(dot.y, dot.fy);
long timeLong = 0;
timeLong = timeLong + ((long) (dotsBytes[index + 12] & FF) << 56);
timeLong = timeLong + ((long) (dotsBytes[index + 13] & FF) << 48);
timeLong = timeLong + ((long) (dotsBytes[index + 14] & FF) << 40);
timeLong = timeLong + ((long) (dotsBytes[index + 15] & FF) << 32);
timeLong = timeLong + ((long) (dotsBytes[index + 16] & FF) << 24);
timeLong = timeLong + ((long) (dotsBytes[index + 17] & FF) << 16);
timeLong = timeLong + ((long) (dotsBytes[index + 18] & FF) << 8);
timeLong = timeLong + ((long) (dotsBytes[index + 19] & FF));

我们会发现,long 这家伙居然要占8b, 我灵机一动(时间戳是有规律的)。

byte bytes[] = new byte[8];
//        long timeLong = System.currentTimeMillis();
        long timeLong = 33198110775000L; //3022-01-03 17:26:15  这个long 也只需要6byte 就
//        long timeLong = 33198110775000L/1000;
        System.out.println(timeLong);
        //直接赋值
//        bytes[0] = (byte) (timeLong >> 56);
//        bytes[1] = (byte) (timeLong >> 48);
        bytes[2] = (byte) (timeLong >> 40);
        bytes[3] = (byte) (timeLong >> 32);
        bytes[4] = (byte) (timeLong >> 24);
        bytes[5] = (byte) (timeLong >> 16);
        bytes[6] = (byte) (timeLong >> 8);
        bytes[7] = (byte) timeLong;
        for (byte aByte : bytes) {
            System.out.println(aByte);
        }

bytes 前面2位是0,没错long 数据范围-9223372036854775808~9223372036854775807,所以又能少2位了,如果记录单位为秒的,少3位。

long now = System.currentTimeMillis();
System.out.println(now);
long passTime = 1641223315620L;
long cipherText = (now ^ passTime);
System.out.println(cipherText);
System.out.println(passTime ^ cipherText);

cipherText 是距离某个过去时间多少毫秒,能反^ 得出真正的毫秒数

1000606024365*10=1827387392  10年时间  ,

147122892800  100年

数越小,所用到的byte 越少

网上更牛逼的方法

一种通用整形数组压缩方法

前端 字节数组的妙用

Lucene 源码系列—— BulkOperationPacked

Lucene 源码系列—— PackedInts

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值