android 字节数据的转换与处理
16lz
2021-01-23
android 字节数据的转换与处理
现在android越来越多用于一些物联网IOT方面的应用,那么久难免会需要处理二进制数据,一般IOT数据通信协议为了减少通信数据量,都会使用字节数据或位标志。但是android的java下,没有无符号数据概念,所以处理起来会有些繁琐。
我依据平时数据传输所需要的应用,写了一个类,可以用来处理相应的无符号数据。
解决了几个问题:
- byte[]数组在建立和初始化时,一定要强制转换。
- 2个字节组合成一个16位无符号或有符号的数据计算。
- 4个字节组合成一个32位无符号或有符号的数据计算。
- 打印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"%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]}8000008080000x80 0x00 0x00 0x80 0x80 0x00
更多相关文章
- 范例解析:学习Android的IPC主板模式
- android的singleInstance启动模式及方法调用
- Android中遇到的简单工厂模式的几种实现
- android activity 四大启动模式及使用场景
- Android在MTP模式下,只显示指定文件夹
- Android——Activity四种启动模式
- 固定屏幕显示模式 ScreenOrientation
- 解决Android编辑框在全屏模式下无法检测布局变化的问题
- 转:Android下文件操作模式(含SDCard的读写)