Разбор двоичных данных
У меня есть приложение, которое получает данные в двоичном виде через Bluetooth. Я читаю данные, используя inputtream из bluetoothsocket в байт []. Но я должен проанализировать все сообщения, потому что они должны иметь заданный формат, чтобы быть действительными. Все сообщения в двоичном виде.
Моим решением было преобразовать byte[] в строку, а затем разбить строку и проанализировать все полученные сообщения.
Пример разбора данных: 0000000010000001
я должен знать, что первые 8 нулей - это заголовок, а 10000001 - реальные данные.
Моя идея состояла в том, чтобы создать строку (из байта []), которая представляет -> 0000000010000001, используя новую строку (byte[]), а затем разделить всю строку в один байт и проверить значение, например:
строка1 имела 00000000 строка2 имела 10000001
я знаю, что 8 нулей являются заголовком, поэтому string2 имеет представление данных.
Мой вопрос об эффективности этого метода. Это лучший способ сделать это в мобильной среде?
4 ответа
Манипулирование строками для анализа двоичных данных довольно неэффективно с точки зрения скорости, потребления памяти, а также накладывает определенную нагрузку на сборщик мусора - потому что вы всегда генерируете новые строковые объекты и сразу же забываете их.
В Java у вас есть несколько вариантов сделать это лучше:
DataInputStream
: это обертка дляInputStream
где вы читаете байты, шорты, длинные, двойные и т. д. прямо из потока.- Используя NIO
ByteBuffers
и "производные" типы, такие какShortBuffer
... они хороши для передачи больших объемов данных, а также для двоичного анализа.
Пока ваши данные выровнены по байтам, это простые способы. Если это не так - тогда лучше узнать, как выполнять битовые манипуляции с помощью таких операторов, как &
, |
, ~
, <<
, >>
,
Я предлагаю вам придерживаться DataInputStream
как можно дольше.
Только для справки, есть бесплатная библиотека OSS, называемая Java Binary Block Parser (JBBP), она совместима с Android (2.1+) и позволяет просто описывать структуру данных в текстовом формате и автоматически анализировать поток данных (или массив), если вы хотите для разбора всего потока на биты он может быть выполнен в одной строке
byte [] parsedBits = JBBPParser.prepare("bit:1 [_];").parse(new byte[]{1,2,3,4,5}).findFieldForType(JBBPFieldArrayBit.class).getArray();
Строки - наименее эффективный способ сделать это действительно.
Если ваш бинарный 0000000010000001
на самом деле byte[] {0, 0, 0, 0, 2, 0, 0, 1}
в десятичном, затем просто проверьте, если b[0] == b[1] == b[3] == b[4] == 0
,
Редактировать: игнорировать "в десятичной" части, это не имеет значения, если вы хотите только проверить, если ваш массив начинается с 00000000
(т.е. 4 нулевых байта)
Это очень низкоэффективный способ, и не рекомендуется. Чтобы анализировать двоичные данные, у нас должен быть протокол и всегда использовать битовую операцию. Если вы не знакомы с этим,
FastProto - лучший выбор, вам нужно аннотировать поля объекта данных, FastProto поможет вам завершить все.
Представьте, что двоичные данные имеют фиксированную длину 20 байт:
65 00 7F 69 3D 84 7A 01 00 00 55 00 F1 FF 0D 00 00 00 07 00
Двоичные данные содержат 3 различных типа сигналов, конкретный протокол выглядит следующим образом:
import org.indunet.fastproto.annotation.*;
public class Weather {
@UInt8Type(offset = 0)
int id;
@TimeType(offset = 2)
Timestamp time;
@Int16Type(offset = 12)
int temperature;
}
byte[] bytes= ... // binary need parsing
Weather weather = FastProto.parse(datagram, Weather.class);
Возможно, вы заметили, что FastProto описывает информацию о полях в двоичных данных с помощью аннотаций, что очень просто и эффективно.