Парсинг двоичных данных с scala

Я должен проанализировать некоторые простые двоичные файлы. (Файлы содержат n записи, который состоит из нескольких / целых чисел без знака со знаком различных размеров и т.д.),

В момент я делаю парсинг "вручную". Кто-то знает библиотеку, которая помогает сделать этот тип парсинга?

Править: "Рукой" означает, что я добираюсь, Байт Данных Байтом сортируют его в к правильному порядку и преобразовывают его в Интервал/Байт И т.д. Также, некоторые Данные не подписаны.

13
задан nuriaion 19 April 2010 в 14:19
поделиться

4 ответа

Я использовал библиотеку sbinary раньше и это очень приятно. Документация немного скудна, но я бы посоветовал сначала взглянуть на старую вики-страницу , поскольку это дает вам отправную точку. Затем ознакомьтесь со спецификациями тестов, так как это дает вам несколько очень хороших примеров.

Основным преимуществом sbinary является то, что он дает вам способ описать формат связи каждого объекта как объект Format. Затем вы можете инкапсулировать эти форматированные типы в объект Format более высокого уровня, и Scala выполняет всю тяжелую работу по поиску этого типа, если вы включили его в текущую область как неявный объект.

Как я говорю ниже, я бы теперь рекомендовал людям использовать scodec вместо sbinary. В качестве примера использования scodec я реализую, как читать двоичное представление в памяти следующей структуры C:

struct ST
{
   long long ll; // @ 0
   int i;        // @ 8
   short s;      // @ 12
   char ch1;     // @ 14
   char ch2;     // @ 15
} ST;

Соответствующим классом сценария Scala будет:

case class ST(ll: Long, i: Int, s: Short, ch1: String, ch2: String)

Я немного упрощаю задачу для я просто сказал, что мы храним строки вместо символов, и я скажу, что это символы UTF-8 в структуре. Я также не занимаюсь подробностями порядка байтов или фактическим размером типов long и int в этой архитектуре и просто предполагаю, что они равны 64 и 32 соответственно.

Парсеры Scodec обычно используют комбинаторы для построения парсеров более высокого уровня из парсеров более низкого уровня. Итак, ниже мы определим парсер, который объединяет 8-байтовое значение, 4-байтовое значение, 2-байтовое значение, 1-байтовое значение и еще одно 1-байтовое значение. Результатом этой комбинации является кодек Tuple:

val myCodec: Codec[Long ~ Int ~ Short ~ String ~ String] = 
  int64 ~ int32 ~ short16 ~ fixedSizeBits(8L, utf8) ~ fixedSizeBits(8L, utf8)

Затем мы можем преобразовать его в класс случая ST, вызвав на нем функцию xmap , которая принимает две функции, одна для превращения кодека Tuple в место назначения. type и другую функцию, чтобы взять целевой тип и преобразовать его в форму Tuple:

val stCodec: Codec[ST] = myCodec.xmap[ST]({case ll ~ i ~ s ~ ch1 ~ ch2 => ST(ll, i, s, ch1, ch2)}, st => st.ll ~ st.i ~ st.s ~ st.ch1 ~ st.ch2)

Теперь вы можете использовать кодек следующим образом:

stCodec.encode(ST(1L, 2, 3.shortValue, "H", "I"))
res0: scodec.Attempt[scodec.bits.BitVector] = Successful(BitVector(128 bits, 0x00000000000000010000000200034849))

res0.flatMap(stCodec.decode)
=> res1: scodec.Attempt[scodec.DecodeResult[ST]] = Successful(DecodeResult(ST(1,2,3,H,I),BitVector(empty)))

Я бы посоветовал вам взглянуть на Scaladocs, а не на Guide, поскольку там гораздо подробнее в Scaladocs. Руководство - хорошее начало с самых основ, но оно не особо касается части композиции, но Scaladocs это довольно хорошо охватывает.

7
ответ дан 1 December 2019 в 23:47
поделиться

Я не знаю, что вы имеете в виду под словом «вручную», но использую простой DataInputStream (apidoc здесь ) довольно краток и ясен:

val dis = new DataInputStream(yourSource)

dis.readFloat()
dis.readDouble()
dis.readInt()
// and so on

Взято из другого вопроса SO : http://preon.sourceforge.net/ , это должна быть структура для двоичного кодирования / декодирование ... посмотрите, есть ли у него необходимые вам возможности

4
ответ дан 1 December 2019 в 23:47
поделиться

Сам Scala не имеет библиотеки ввода двоичных данных, но пакет java.nio неплохо справляется. Он не обрабатывает беззнаковые данные явно, как и Java, поэтому вам нужно выяснить, как вы хотите ими управлять, но у него есть удобные методы «get», которые учитывают порядок байтов.

4
ответ дан 1 December 2019 в 23:47
поделиться

Если вы ищете решение на основе Java, то я бессовестно вставлю Preon. Вы просто аннотируете структуру данных Java в памяти, запрашиваете у Preon кодек, и все готово.

1
ответ дан 1 December 2019 в 23:47
поделиться
Другие вопросы по тегам:

Похожие вопросы: