android 字节数据的转换与处理

android 字节数据的转换与处理

现在android越来越多用于一些物联网IOT方面的应用,那么久难免会需要处理二进制数据,一般IOT数据通信协议为了减少通信数据量,都会使用字节数据或位标志。但是android的java下,没有无符号数据概念,所以处理起来会有些繁琐。
我依据平时数据传输所需要的应用,写了一个类,可以用来处理相应的无符号数据。
解决了几个问题:

  1. byte[]数组在建立和初始化时,一定要强制转换。
  2. 2个字节组合成一个16位无符号或有符号的数据计算。
  3. 4个字节组合成一个32位无符号或有符号的数据计算。
  4. 打印16进制形式的数组,方便调试,和对照协议进行查看。
    以上表达不全面,直接上代码,后面有应用的例子:
public class Bytes{
    /**
     * 字节数组的容量
     */
    int mCap = 0;
    /**
     * 实际字节数组容器
     */
    byte[] mBytes;

    /**
     * 通过设定字节数组容量来构建对象
     * @param cap   int 字节数组容量
     */
    public Bytes(int cap) {
        mBytes = new byte[cap];
        mCap = cap;
    }

    /**
     * 默认构建字节数组为容量为4
     */
    public Bytes() {
        mBytes = new byte[4];
        mCap = 4;
    }

    /**
     * 通过已有byte[]进行构建对象,同时设定容器容量
     * @param mBytes    byte[]
     */
    public Bytes(byte[] mBytes) {
        this.mBytes = mBytes;
        mCap = mBytes.length;
    }

    /**
     * 通过已有int[]进行构建对象,同时设定容器容量,会把int型强制转换为byte型,超过范围都按0xff设定
     * @param mInts int[]
     */
    public Bytes(int[] mInts) {
        mCap = mInts.length;
        mBytes = new byte[mCap];
        for (int i = 0; i < mCap; i++) {
            if (mInts[i] > 255) {
                this.mBytes[i] = (byte) 255;
            } else {
                this.mBytes[i] = (byte) (mInts[i] & 0xff);
            }
        }
    }

    /**
     * 从容器中指定偏移位置读取16位的无符号整形,大端模式
     * @param offset    int 容器偏移量
     * @return          int 返回16位无符号整形,大端模式
     */
    public int readUInt16BE(int offset) {
        int res = 0;
        if (mBytes != null && (mCap-offset) >= 2) {
            res = ((mBytes[offset] & 0xff) << 8) + (mBytes[offset + 1] & 0xff);
        }
        return res;
    }

    /**
     * 从容器起始位置读取16位无符号整形,大端模式
     * @return int  返回16位无符号整形,大端模式
     */
    public int readUInt16BE() {
        return readUInt16BE(0);
    }

    /**
     * 从容器中指定偏移位置读取16位的无符号整形,小端模式
     * @param offset    int 容器偏移量
     * @return          int 返回16位无符号整形,小端模式
     */
    public int readUInt16LE(int offset) {
        int res = 0;
        if (mBytes != null && (mCap-offset) >= 2) {
            res = ((mBytes[offset + 1] & 0xff) << 8) + (mBytes[offset] & 0xff);
        }
        return res;
    }

    /**
     * 从容器中指定偏移位置读取16位的无符号整形,小端模式
     * @return  int 返回16位无符号整形,小端模式
     */
    public int readUInt16LE() {
        return readUInt16LE(0);
    }

    /**
     * 从容器中指定偏移位置读取32位的无符号整形,大端模式
     * @param offset    int     容器偏移量
     * @return          long    返回32位无符号整形,大端模式
     */
    public long readUInt32BE(int offset) {
        long res = 0;
        if (mBytes != null && (mCap-offset) >= 4) {
            res = ((mBytes[offset] & 255L) << 24) + ((mBytes[offset + 1] & 255L) << 16) + ((mBytes[offset + 2] & 0x255L) << 8) + (mBytes[offset + 3] & 0x255L);
        }
        return res;
    }

    /**
     * 从容器中指定偏移位置读取32位的无符号整形,大端模式
     * @return  long    返回32位无符号整形,大端模式
     */
    public long readUInt32BE() {
        return readUInt32BE(0);
    }

    /**
     * 从容器中指定偏移位置读取32位的无符号整形,小端模式
     * @param offset    int     容器偏移量
     * @return          long    返回32位无符号整形,小端模式
     */
    public long readUInt32LE(int offset) {
        long res = 0;
        if (mBytes != null && (mCap-offset) >= 4) {
            res = ((mBytes[offset + 3] & 255L) << 24) + ((mBytes[offset + 2] & 255L) << 16) + ((mBytes[offset + 1] & 0x255L) << 8) + (mBytes[offset] & 0x255L);
        }
        return res;
    }

    /**
     * 从容器中指定偏移位置读取32位的无符号整形,小端模式
     * @return  long    返回32位无符号整形,小端模式
     */
    public long readUInt32LE() {
        return readUInt32LE(0);
    }

    /**
     * 从容器中指定偏移位置读取16位的有符号整形,大端模式
     * @param offset    int 容器偏移量
     * @return          int 返回16位有符号整形,大端模式
     */
    public int readInt16BE(int offset) {
        int res = 0;
        if (mBytes != null && (mCap-offset) >= 2) {
            res = (mBytes[offset] << 8) + mBytes[offset+1];
        }
        return res;
    }

    /**
     * 从容器中指定偏移位置读取16位的有符号整形,大端模式
     * @return  int 返回16位有符号整形,大端模式
     */
    public int readInt16BE(){
        return readInt16BE(0);
    }

    /**
     * 从容器中指定偏移位置读取16位的有符号整形,小端模式
     * @param offset    int 容器偏移量
     * @return          int 返回16位有符号整形,小端模式
     */
    public int readInt16LE(int offset) {
        int res = 0;
        if (mBytes != null && (mCap-offset) >= 2) {
            res = (mBytes[offset+1] << 8) + mBytes[offset];
        }
        return res;
    }

    /**
     * 从容器中指定偏移位置读取16位的有符号整形,小端模式
     * @return  int 返回16位有符号整形,小端模式
     */
    public int readInt16LE(){
        return readInt16LE(0);
    }

    /**
     * 从容器中指定偏移位置读取32位的有符号整形,大端模式
     * @param offset    int     容器偏移量
     * @return          long    返回32位有符号整形,大端模式
     */
    public long readInt32BE(int offset) {
        long res =0;
        if (mBytes != null && (mCap-offset) >= 4) {
            res = (mBytes[offset] << 24) + (mBytes[offset+1] << 16) + (mBytes[offset+2] << 8) + mBytes[offset+3];
        }
        return res;
    }

    /**
     * 从容器中指定偏移位置读取32位的有符号整形,大端模式
     * @return  long    返回32位有符号整形,大端模式
     */
    public long readInt32BE(){
        return readInt32BE(0);
    }

    /**
     * 从容器中指定偏移位置读取32位的有符号整形,小端模式
     * @param offset    int     容器偏移量
     * @return          long    返回32位有符号整形,小端模式
     */
    public long readInt32LE(int offset) {
        long res =0;
        if (mBytes != null && (mCap-offset) >= 4) {
            res = (mBytes[offset+3] << 24) + (mBytes[offset+2] << 16) + (mBytes[offset+1] << 8) + mBytes[offset];
        }
        return res;
    }

    /**
     * 从容器中指定偏移位置读取32位的有符号整形,小端模式
     * @return  long 返回32位有符号整形,小端模式
     */
    public long readInt32LE(){
        return readInt32LE(0);
    }

    /**
     * 获得容器容量
     * @return  int 容器容量
     */
    public int length() {
        return mCap;
    }

    /**
     * 连接另一个byte[],可设定来源数据的起始位置,以及长度,也可设定目标数据的连接起始位置
     * @param offsetT   int     目标数据的连接起始位置
     * @param b         byte[]  来源数据
     * @param offset    int     来源数据起始位置
     * @param length    int     来与数据长度
     */
    public void cat(int offsetT, byte[] b, int offset, int length) {
        byte[] tmp = mBytes;
        mCap = offsetT + length;
        mBytes = new byte[mCap];
        for (int i = 0; i < offsetT; i++) {
            mBytes[i] = tmp[i];
        }
        for (int i = 0; i < length; i++) {
            mBytes[i + offsetT] = b[i + offset];
        }
    }

    /**
     * 连接另一个byte[],可设定来源数据的起始位置,以及长度,连接到目标数据的尾部
     * @param b         byte[]  来源数据
     * @param offset    int     来源数据起始位置
     * @param length    int     来与数据长度
     */
    public void cat(byte[] b, int offset, int length) {
        cat(mCap, b, offset, length);
    }

    /**
     * 连接另一个byte[],可设定来源数据的起始位置到结尾,连接到目标数据的尾部
     * @param b         byte[]  来源数据
     * @param offset    int     来源数据起始位置
     */
    public void cat(byte[] b, int offset) {
        cat(b, offset, b.length - offset);
    }

    /**
     * 连接另一个byte[],来源数据全部连接到目标数据的尾部
     * @param b byte[]  来源数据
     */
    public void cat(byte[] b) {
        cat(b, 0);
    }

    /**
     * 获得实际容器的byte[]数组
     * @return  byte[]
     */
    public byte[] toBytes() {
        return mBytes;
    }

    /**
     * 输出对象全部属性
     * @return  String
     */
    @Override
    public String toString() {
        return "Bytes{" +
                "length=" + mCap +
                ", data=" + Arrays.toString(mBytes) +
                '}';
    }

    /**
     * 输出16进制的数据,每个数据前可增加前缀header,数据之间可增加间隔space
     * @param header    String  前缀
     * @param space     String  间隔
     * @return          String
     */
    public String toHexString(String header,String space){
        StringBuffer buffer = new StringBuffer();
        for(int i=0;i<mCap;i++){
            buffer.append(String.format("%s%02x%s",header,mBytes[i],space));
        }
        return buffer.substring(0,buffer.length()-space.length());
    }

    /**
     * 输出16进制的数据,数据之间可增加间隔space
     * @param space     String  间隔
     * @return          String
     */
    public String toHexString(String space){
        return toHexString("",space);
    }

    /**
     * 输出16进制的数据
     * @return  String
     */
    public String toHexString(){
        return toHexString("");
    }
}

应用示例:

@Test
    public void addition_isCorrect() throws Exception {
        Bytes bytes = new Bytes(new int[]{0x80,0x00});
        int tt = bytes.readUInt16BE();
        int mm = bytes.readInt16BE();
        Bytes bb = new Bytes(new int[]{0x80, 0, 0, 128});
        long ii = bb.readUInt16BE(2);
        long nn = bb.readInt16BE(2);
        bb.cat(bytes.toBytes());
        int ll = bb.readUInt16BE(4);
        System.out.print(Arrays.toString(bb.toBytes())+"\r\n");
        System.out.print(bb.toString()+"\r\n");
        System.out.print(bb.toHexString()+"\r\n");
        System.out.print(bb.toHexString("0x"," ")+"\r\n");
    }

输出

[-128, 0, 0, -128, -128, 0]
Bytes{length=6, data=[-128, 0, 0, -128, -128, 0]}
800000808000
0x80 0x00 0x00 0x80 0x80 0x00
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值