java типове данни към байтов масив

Имам Java клас

public class MsgLayout{
int field1;
String field2;
long field3;
}

Трябва да напиша този обект като байтов масив в изходен поток на Socket. Трите полета (променливи на инстанция) имат оформление. т.е. field1 трябва да заема 1 байт, field2 трябва да заема 4 байта и field3 трябва да заема 8 байта.

ByteBuffer bbf = ByteBuffer.allocate(TOTAL_SIZE);
bbf.put(Integer.toString(this.getField1()).getBytes(), 0, FIELD1_SIZE);
bbf.position(FIELD2_OFFSET);
bbf.put(Long.toString(this.getField2()).getBytes(), 0, FIELD2_SIZE);
bbf.position(FIELD3_OFFSET);
bbf.put(Long.toString(this.getField3()).getBytes(), 0, FIELD3_SIZE);
byte[] msg = bbf.array();

Използвайки горния код, се опитвам да побера всяко поле в байтовия масив според желания размер. Но получавам IndexOutOfBoundException Накратко, проблемът е как да се поберат полетата в размера, дефиниран от оформлението. Например FIELD1_OFFSET = 0, FIELD1_SIZE=1, FIELD2_OFFSET=1, FIELD2_SIZE=4, FIELD3_OFFSET=5, FIELD3_SIZE=8. Сега, когато преобразувам field1 в низ, той не се побира в 1 байт, когато се преобразува в байт []. Ако не преобразувам в String и използвам putInt(int), той записва 4 байта в получения масив от байтове.


person hoshang.varshney    schedule 28.09.2011    source източник
comment
Освен ако не можете да гарантирате обхвата на вашите полета, ще загубите данни, когато се опитате да ги съхраните в твърде малки слотове с фиксиран размер в буфера. Как смятате да разрешите това?   -  person kdgregory    schedule 28.09.2011
comment
Какво имаш предвид под диапазон? Не мога ли да побера Integer в един байт? Не мога ли да съхраня низ в 4 байта?   -  person hoshang.varshney    schedule 28.09.2011
comment
@hoshang.varshney, int в Java е 4 байта, а низът е с променлива дължина. Когато казвате String, мислите ли за char, т.е. единичен знак? В Java дори един символ заема 2 байта, тъй като използва уникод.   -  person Mike Deck    schedule 29.09.2011
comment
Имам предвид String (променлива дължина). Предполагам, че ще трябва да запазя максималната дължина на field2 като 4, за да се побере в съобщението.   -  person hoshang.varshney    schedule 29.09.2011


Отговори (2)


Това, което вашият код прави в момента, е да кодира вашите цифрови полета като низове и след това да извежда байтовете на тези знаци.

Бих предложил да използвате класа DataOutputStream, за да обвиете вашия SocketOutput поток и да запишете вашите двоични данни по следния начин:

DataOutput output = new DataOutputStream(socketOutputStream);

int field1 = 1;
String field2 = "Hello";
long field3 = 5000000000L;

output.writeByte(field1);
output.writeBytes(field2.substring(0, 3));
output.writeLong(field3);

В този код има няколко предположения. Първо предполагам, че за поле 2 искате 4 символа, сериализирани като един байт всеки. Ако искате да направите многобайтово кодиране, използвайки нещо като UTF-8, тогава трябва да направите нещо малко по-различно. Второ, предполагам, че поле 2 винаги ще има поне 4 знака.

person Mike Deck    schedule 28.09.2011

field1 може да има само един байт данни, но неговото представяне на низ ще бъде един или повече знака (напр. "0", "63", "127"). Всеки знак в низа всъщност е char (двубайтова стойност). Така че бих очаквал един байт данни да се раздуе до два до шест байта данни, когато премине през преобразуване на байт->Низ->байт[].

person pamphlet    schedule 28.09.2011