2015-11-19 79 views
1

我需要从混合的数据类型构造一个Java字节数组,但我不知道如何做到这一点。这是我的类型:如何将混合Java数据类型转换为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 

我知道该字符串,我可以使用

message.getBytes("US_ASCII"); 

我知道了int类型,我可以使用

Integer.byteValue(); 

我知道短值,我可以使用

Short.byteValue(); 

而通过te值已经是字节,我只是不确定如何将所有这些组合到单个字节数组中。我看了一下

System.arraycopy(); 

这是正确的过程中,我只是将所有的数据字节,并开始“串联”的字节数组arraycopy?

我正在与一些远程服务器进行通信,我无法控制,而这是他们需要的消息过程。

+0

'Integer.byteValue();'会给你一个'byte'。据推测,你想要4. –

+1

有几种方法。你提到的那些是有损的,这意味着你会丢失信息。 (例如,如果您的int为'23467',则不适合单个字节,'é'不适用于US-ASCII编码)。你需要首先知道预期的格式是什么。 – njzk2

+0

@ njzk2我不确定你在问什么。在我的问题中,我所具有的价值观基本上是他们永远都会做的。 – Brian

回答

0

所有,我想发布我自己的解决方案,我的问题在这里。我在how to insert a short into java byte array上进行了一次Google搜索。其中一个结果谈到了Java ByteBuffer。经过一番阅读后,我确定这是获得我需要的结果的最好和最快捷的方式。在Java API,真正让我感兴趣的字节缓冲区中的一个部分是这样的:

在这个类不返回其他值返回被指定为返回后调用它们的缓冲方法。这允许方法调用被链接。声明

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

这很简单,而且正是我所需要的。谢谢所有花时间阅读和回复的人。

1

如果有一个“混合型”你的意思是不同的成员字段类型的一类,再一个方法是使你的类serializable,并使用ApacheUtils

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

你如何强制这个返回协议中预期的格式? –

+0

@SotiriosDelimanolis也许我误解了这个问题。他不能只是在另一端反序列化它吗? –

+0

_I与我无法控制的远程服务器通信,这是他们所需的消息过程._ –

0

当然,你可以用arrayCopy串联这些值,正如你所建议的那样。

您还可以将您的字节追加到ByteArrayOutputStream

关键是要准确理解接收系统的期望。它如何知道一个领域的结局和下一个领域的开始?它如何知道它在流中给定位置上读取的是什么类型?有很多方法可以选择这样做 - 在协议中使用长度标题;带类型标题;以字符串的空终止;具有设定的字段顺序和长度;等等。

无论您选择什么方法,都要编写单元测试,检查边缘情况,如负数,非常大的数字,非ASCII文本等。当一切工作正常时,很容易被蜇伤,然后突然服务器扼杀一个Unicode字符或负数,它被解释为一个非常大的数字。

Google的protocol buffers图书馆还有一个选项 - 可能对您的需求略微矫枉过正,但灵活且性能卓越。

2

围绕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完全类似于上面的代码,完全相反(从字节数组中提取值)。

相关问题