[英]How do I convert mixed Java data types into a Java byte array?
我需要用混合数据类型构造一个Java字节数组,但我不知道如何做到这一点。 这些是我的类型:
byte version = 1; // at offset 0
short message_length = // the size of the byte[] message I am constructing here, at offset 1
short sub_version = 15346; // at offset 3
byte message_id = 2; // at offset 5
int flag1 = 10; // at offset 6
int flag2 = 0; // at offset 10
int flag3 = 0; // at offset 14
int flag4 = 0; // at offset 18
String message = "the quick brown fox jumps over the lazy dog"; // at offset 22
我知道String,我可以使用
message.getBytes("US_ASCII");
我知道int值,我可以使用
Integer.byteValue();
我知道短期值,我可以使用
Short.byteValue();
并且字节值已经是字节,我只是不确定如何将所有这些组合成单个字节数组。 我读过了
System.arraycopy();
这是正确的过程,我只是将所有数据转换为字节,并开始使用arraycopy“连接”字节数组?
我正在与一些我无法控制的远程服务器通信,这是他们需要的消息过程。
围绕ByteArrayOutputStream
包装DataOutputStream
。 通过这种方式,您可以将所有原始类型(如int
和short
直接写入DataOutputStream
,后者将它们转换为字节并将它们转发到ByteArrayOutputStream
,然后您可以从中检索整个事物作为一个字节数组:
ByteArrayOutputStream bOut = new ByteArrayOutputStream();
DataOutputStream dOut = new DataOutputStream(bOut);
dOut.writeByte(version);
dOut.writeShort(message_length);
dOut.writeShort(sub_version);
dOut.writeByte(message_id);
dOut.writeInt(flag1);
dOut.writeInt(flag2);
dOut.writeInt(flag3);
dOut.writeInt(flag4);
dOut.write(message.getBytes(), 0, message.length());
dOut.flush();
byte[] result = bOut.toByteArray();
关于这一点最好的事情是你可以完全相反(从字节数组中提取值)与DataInputStream
和ByteArrayInputStream
完全类似于上面的代码。
如果通过'混合类型'表示具有不同成员字段类型的类,则一种方法是使您的类可序列化 ,并使用ApacheUtils
byte[] data = SerializationUtils.serialize(yourObject);
当然,正如您所建议的arrayCopy
,您可以使用arrayCopy
连接这些值。
您还可以将字节附加到ByteArrayOutputStream
。
关键是要准确理解接收系统的期望。 它如何知道一个字段的结束和下一个字段的开始? 它是如何知道它在流中给定位置读取的类型? 有很多方法可以选择这样做 - 在协议中使用长度标题; 带有类型标题; 使用字符串的空终止; 具有一定的字段顺序和长度; 等等。
无论选择哪种方法,都要编写单元测试来检查边数情况,如负数,非常大的数字,非ASCII文本等。 当一切工作正常时,很容易被蜇到,然后突然服务器扼杀一个Unicode字符或一个负数,它解释为一个非常大的数字。
另一个选择 - 对您的需求可能略微过度,但灵活且具有高性能 - 是Google的protocol buffers
库。
总之,我想在这里发布我自己的解决方案。 我做了一个关于如何在Java字节数组中插入short的快速谷歌搜索。 其中一个结果谈到了Java ByteBuffer 。 经过一番阅读,我确定这是我获得所需结果的最佳和最快捷方式。 Java API中的一个真正让我对ByteBuffer感兴趣的部分是这样的:
此类中没有返回值的方法被指定为返回调用它们的缓冲区。 这允许链接方法调用。 陈述的顺序
bb.putInt(0xCAFEBABE);
bb.putShort(3);
bb.putShort(45);
例如,可以用单个语句替换
bb.putInt(0xCAFEBABE).putShort(3).putShort(45);
所以,这就是我所做的:
byte version = 1;
short message_length = 72;
short sub_version = 15346;
byte message_id = 2;
int flag1 = 10;
int flag2 = 0;
int flag3 = 0;
int flag4 = 0;
String message = "the quick brown fox jumps over the lazy dog";
ByteBuffer messageBuffer = ByteBuffer.allocate(message_length);
messageBuffer.put(version).putShort(message_length).putShort(sub_version).put(message_id).putInt(flag1).putInt(flag2).putInt(flag3).putInt(flag4).put(message.getBytes());
byte[] myArray = messageBuffer.array();
这很快捷,而且正是我所需要的。 谢谢所有花时间阅读和回复的人。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.