типы данных 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, целое число в Java не равно 4 байтам, а строка имеет переменную длину. Когда вы говорите String, вы думаете о символе, то есть об одном символе? В Java даже один символ занимает 2 байта, поскольку он использует юникод.   -  person Mike Deck    schedule 29.09.2011
comment
Я имею в виду строку (переменной длины). Я предполагаю, что мне придется сохранить максимальную длину 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 (двухбайтовое значение). Поэтому я ожидаю, что один байт данных увеличится до двух-шести байтов данных, когда он пройдет через преобразование byte->String->byte[].

person pamphlet    schedule 28.09.2011