2015-11-19 81 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完全類似於上面的代碼,完全相反(從字節數組中提取值)。

相關問題