简体   繁体   English

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

[英]How do I convert mixed Java data types into a Java byte array?

I need to construct a Java byte array out of mixed data types, but I don't know how to do this. 我需要用混合数据类型构造一个Java字节数组,但我不知道如何做到这一点。 These are my types: 这些是我的类型:

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

I know for the String, I can use 我知道String,我可以使用

message.getBytes("US_ASCII");

I know for the int values, I can use 我知道int值,我可以使用

Integer.byteValue();

I know for the short values, I can use 我知道短期值,我可以使用

Short.byteValue();

And the byte values are already bytes, I am just not sure of how to combine all of these into a single byte array. 并且字节值已经是字节,我只是不确定如何将所有这些组合成单个字节数组。 I have read about 我读过了

System.arraycopy();

Is this the correct process, I just convert all the data to bytes, and start "concatenating" the byte array with arraycopy? 这是正确的过程,我只是将所有数据转换为字节,并开始使用arraycopy“连接”字节数组?

I am communicating with some distant server I have no control over, and this is the message process they require. 我正在与一些我无法控制的远程服务器通信,这是他们需要的消息过程。

Wrap a DataOutputStream around a ByteArrayOutputStream . 围绕ByteArrayOutputStream包装DataOutputStream This way you can write all the primitive types like int and short directly to the DataOutputStream , which converts them to bytes and forwards them to the ByteArrayOutputStream , from which you can then retrieve the whole thing as one byte array: 通过这种方式,您可以将所有原始类型(如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();

The best thing about this is that you can do the exact opposite (extracting values from a byte array) with DataInputStream and ByteArrayInputStream completely analoguously to the above code. 关于这一点最好的事情是你可以完全相反(从字节数组中提取值)与DataInputStreamByteArrayInputStream完全类似于上面的代码。

如果通过'混合类型'表示具有不同成员字段类型的类,则一种方法是使您的类可序列化 ,并使用ApacheUtils

byte[] data = SerializationUtils.serialize(yourObject);

Certainly you can concatenate these values with arrayCopy , as you've suggested. 当然,正如您所建议的arrayCopy ,您可以使用arrayCopy连接这些值。

You can also append your bytes onto a ByteArrayOutputStream . 您还可以将字节附加到ByteArrayOutputStream

The key is to understand exactly what the receiving system is expecting. 关键是要准确理解接收系统的期望。 How does it know where one field ends and the next begins? 它如何知道一个字段的结束和下一个字段的开始? How does it know what type it's reading at a given position in the stream? 它是如何知道它在流中给定位置读取的类型? There are lots of ways they could have chosen to do that - with length headers in the protocol; 有很多方法可以选择这样做 - 在协议中使用长度标题; with type headers; 带有类型标题; with null-termination of strings; 使用字符串的空终止; with a set order of fields and their lengths; 具有一定的字段顺序和长度; and so on. 等等。

Whatever method you choose, write unit tests that check for edge cases like negative numbers, very large numbers, non-ASCII text and so on. 无论选择哪种方法,都要编写单元测试来检查边数情况,如负数,非常大的数字,非ASCII文本等。 It's easy to get stung when everything has been working fine, then suddenly the server chokes on a Unicode character or a negative number that it interprets as a very large number. 当一切工作正常时,很容易被蜇到,然后突然服务器扼杀一个Unicode字符或一个负数,它解释为一个非常大的数字。

One other option -- perhaps slight overkill for your needs, but flexible and with high performance -- is Google's protocol buffers library. 另一个选择 - 对您的需求可能略微过度,但灵活且具有高性能 - 是Google的protocol buffers库。

All, I wanted to post my own solution to my problem here. 总之,我想在这里发布我自己的解决方案。 I did a quick Google search on how to insert a short into java byte array . 我做了一个关于如何在Java字节数组中插入short的快速谷歌搜索。 One of the results talked about a Java ByteBuffer . 其中一个结果谈到了Java ByteBuffer After some reading, I determined this was the best and quickest way for me to get the results I needed. 经过一番阅读,我确定这是我获得所需结果的最佳和最快捷方式。 One section in the Java API that really made me interested in the ByteBuffer was this: Java API中的一个真正让我对ByteBuffer感兴趣的部分是这样的:

Methods in this class that do not otherwise have a value to return are specified to return the buffer upon which they are invoked. 此类中没有返回值的方法被指定为返回调用它们的缓冲区。 This allows method invocations to be chained. 这允许链接方法调用。 The sequence of statements 陈述的顺序

bb.putInt(0xCAFEBABE);
bb.putShort(3);
bb.putShort(45);

can, for example, be replaced by the single statement 例如,可以用单个语句替换

bb.putInt(0xCAFEBABE).putShort(3).putShort(45);

So, that is what I did: 所以,这就是我所做的:

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();

That was fast and easy, and just what I needed. 这很快捷,而且正是我所需要的。 Thank you all who took the time to read and reply. 谢谢所有花时间阅读和回复的人。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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