繁体   English   中英

如何将混合Java数据类型转换为Java字节数组?

[英]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 通过这种方式,您可以将所有原始类型(如intshort直接写入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();

关于这一点最好的事情是你可以完全相反(从字节数组中提取值)与DataInputStreamByteArrayInputStream完全类似于上面的代码。

如果通过'混合类型'表示具有不同成员字段类型的类,则一种方法是使您的类可序列化 ,并使用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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM