2015-11-19 4 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(); 

И по те значения уже являются байтами, я просто не уверен, как объединить их все в один массив байтов. Я прочитал о

System.arraycopy(); 

Является ли это правильный процесс, я просто конвертировать все данные в байты, и начать «конкатенацию» массив байт с ArrayCopy?

Я общаюсь с каким-то отдаленным сервером. Я не контролирую, и это процесс сообщения, который им нужен.

+0

'Integer.byteValue();' даст вам один 'byte'. Предположительно, вы хотите 4. –

+1

существует несколько методов. те, кого вы упомянули, являются потерями, то есть вы потеряете информацию. (например, если у вас есть int, то есть '23467', он не будет входить в один байт, а' é' не будет работать с кодировкой US-ASCII'. Сначала вам нужно знать, что такое ожидаемый формат. – njzk2

+0

@ njzk2 Я не уверен, что вы просите. Значения, которые у меня есть в моем вопросе, суть, по сути, то, что они будут всегда. – Brian

ответ

0

Все, я хотел опубликовать свое собственное решение проблемы. Я сделал быстрый поиск Google на how to insert a short into java byte array. Один из результатов рассказал о Java ByteBuffer. После некоторого чтения я решил, что это лучший и быстрый способ получить результаты, которые мне нужны. Один из разделов в Java API, который действительно заставил меня интересует ByteBuffer было это:

методы в этом классе, что в противном случае не имеют значения для возврата определены, чтобы возвратить в буфер, на котором они вызываются. Это позволяет привязывать вызовы методов. Последовательность операторов

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

_ Я общаюсь с каким-то отдаленным сервером. Я не контролирую, и это процесс сообщений, который им требуется. –

0

Конечно, вы можете объединить эти значения с arrayCopy, как вы предположили.

Вы также можете добавить свои байты в ByteArrayOutputStream.

Ключ должен точно понимать, что ожидает система приема. Откуда он знает, где заканчивается одно поле, а следующее начинается? Как он знает, какой тип он читает в данной позиции в потоке? Есть много способов, которые они могли бы сделать для этого: с заголовками длины в протоколе; с заголовками типов; с нулевым завершением строк; с заданным порядком полей и их длиной; и так далее.

Какой бы метод вы ни выбрали, напишите единичные тесты, которые проверяют случаи краев, такие как отрицательные числа, очень большие числа, текст без ASCII и т. Д. Легко заглушить, когда все работает нормально, и вдруг сервер задыхается от символа Unicode или отрицательного числа, которое интерпретируется как очень большое число.

Другой вариант - возможно, небольшой перебор для ваших нужд, но гибкий и с высокой производительностью - это библиотека Google protocol buffers.

2

Оберните DataOutputStream вокруг ByteArrayOutputStream. Таким образом, вы можете написать все примитивные типы, как int и short непосредственно к 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(); 

Самое лучшее в этом - то, что вы можете сделать абсолютно противоположное (извлечение значений из массива байтов) с DataInputStream и ByteArrayInputStream полностью аналогично приведенному выше коду.

Смежные вопросы