Java 将消息体转为byte数组
以下以 JT/T808-2013 版中终端通用应答消息(0x0001) 为例(该消息体结构简单,适合入门),实现消息体转 byte 数组:
import java.nio.ByteBuffer; import java.nio.charset.StandardCharsets; /** * JT/T808协议消息体转byte数组示例 * 以0x0001终端通用应答消息为例,消息体结构: * 1. 应答流水号:2字节(无符号短整型) * 2. 应答ID:2字节(无符号短整型) * 3. 应答结果:1字节(0:成功/确认 1:失败 2:消息有误 3:不支持) */ public class JT808MsgBodyEncoder { // 字符编码:JT/T808协议规定使用GBK(此处用GBK兼容的GB2312,效果一致) private static final String CHARSET = "GBK"; /** * 终端通用应答消息体编码 * @param replyFlowId 应答流水号 * @param replyMsgId 应答ID(被应答的消息ID) * @param replyResult 应答结果 * @return 编码后的消息体byte数组 */ public static byte[] encodeTerminalGeneralReply(short replyFlowId, short replyMsgId, byte replyResult) { try { // 1. 计算消息体总长度:2(流水号) + 2(应答ID) + 1(结果) = 5字节 int bodyLength = 2 + 2 + 1; ByteBuffer buffer = ByteBuffer.allocate(bodyLength); buffer.order(java.nio.ByteOrder.BIG_ENDIAN); // 强制大端(协议要求) // 2. 依次写入字段(严格按协议顺序) buffer.putShort(replyFlowId); // 应答流水号:2字节 buffer.putShort(replyMsgId); // 应答ID:2字节 buffer.put(replyResult); // 应答结果:1字节 // 3. 转换为byte数组并返回 return buffer.array(); } catch (Exception e) { throw new RuntimeException("JT808消息体编码失败", e); } } /** * 扩展:字符串字段编码(如终端手机号、车牌等) * @param str 要编码的字符串 * @param fixedLength 协议规定的固定长度(不足补0) * @return 编码后的byte数组 */ public static byte[] encodeString(String str, int fixedLength) { try { byte[] strBytes = str.getBytes(CHARSET); // 创建指定长度的数组,默认填充0 byte[] result = new byte[fixedLength]; // 复制字符串字节(超出则截断,不足则补0) System.arraycopy(strBytes, 0, result, 0, Math.min(strBytes.length, fixedLength)); return result; } catch (Exception e) { throw new RuntimeException("字符串编码失败", e); } } // 测试方法 public static void main(String[] args) { // 测试终端通用应答编码 short flowId = 1234; // 应答流水号 short msgId = 0x0100; // 被应答的消息ID(如0x0100终端注册) byte result = 0; // 应答结果:成功 byte[] bodyBytes = encodeTerminalGeneralReply(flowId, msgId, result); System.out.println("消息体byte数组长度:" + bodyBytes.length); // 输出5 System.out.print("消息体byte数组内容:"); for (byte b : bodyBytes) { System.out.printf("%02X ", b); // 十六进制输出:04 D2 01 00 00 } // 测试字符串编码(如终端手机号13800138000,固定12位) byte[] phoneBytes = encodeString("13800138000", 12); System.out.println("\n手机号编码后:"); for (byte b : phoneBytes) { System.out.printf("%02X ", b); // 输出:31 33 38 30 30 31 33 38 30 30 30 00 } } }
附ByteBuffer介绍
public class ByteBufferReadWrite { public static void main(String[] args) { // ========== 第一步:写数据(编码808协议字段)========== ByteBuffer buffer = ByteBuffer.allocate(5); // 容量5字节 buffer.order(ByteOrder.BIG_ENDIAN); // 808协议必须设置大端 // 写入字段(对应808的0x0001消息体) buffer.putShort((short) 1234); // 应答流水号(2字节) buffer.putShort((short) 0x0100); // 应答ID(2字节) buffer.put((byte) 0); // 应答结果(1字节) // ========== 第二步:切换为读模式(flip())========== // flip()作用:limit = position; position = 0; mark = -1 // 简单说:把“写边界”设为读的上限,指针回到起始位置 buffer.flip(); // ========== 第三步:读数据(解码808协议字段)========== short replyFlowId = buffer.getShort(); // 读2字节(应答流水号) short replyMsgId = buffer.getShort(); // 读2字节(应答ID) byte replyResult = buffer.get(); // 读1字节(应答结果) // 输出结果(验证读写一致性) System.out.println("应答流水号:" + replyFlowId); // 1234 System.out.println("应答ID:" + Integer.toHexString(replyMsgId)); // 100 System.out.println("应答结果:" + replyResult); // 0 // ========== 重置缓冲区(重复使用)========== buffer.clear(); // 不是清空数据,只是重置position=0、limit=capacity } }
有些事情,没经历过不知道原理,没失败过不明白奥妙,没痛苦过不了解真谛。临渊羡鱼,不如退而结网!

浙公网安备 33010602011771号