用scala解析二进制数据

我需要解析一些简单的二进制文件. (文件包含n个条目,由不同大小的多个有符号/无符号整数等组成)

在这一刻,我手工解析.有人知道有助于进行这种解析的库吗?

编辑:“手工”意味着我将数据字节By Byte排序到正确的Order并将其转换为Int / Byte等.还有一些数据是无符号的.

解决方法

我以前使用过 sbinary图书馆,这非常好.文件有点稀疏,但我建议先看看旧的 wiki page,因为这给你一个起点.然后查看测试规范,因为这给了你一些非常好的例子.

sbinary的主要优点是它为您提供了一种将每个对象的线格式描述为Format对象的方式.然后,您可以将这些格式化的类型封装在更高级别的Format对象中,Scala只要将其作为隐式对象包含在当前作用域中,就可以重新查找该类型.

如下所述,我现在建议人们使用scodec而不是sbinary.作为如何使用scodec的例子,我将实现如何读取以下C struct的内存中的二进制表示形式:

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)

我正在使自己的事情变得容易一些,只是说我们正在存储Strings而不是Chars,我会说它们在结构体中是UTF-8字符.我也没有处理这个架构的endian细节或long和int类型的实际大小,只是假设它们分别是64和32.

Scodec解析器通常使用组合器来构建较低级解析器.所以在下面我们来定义一个解析器,它结合了一个8字节的值,一个4字节的值,一个2字节的值,一个1字节的值和一个1个字节的值.这种组合的返回是一个元组编解码器:

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

然后,我们可以通过调用它的xmap函数将其转换成ST case类,它需要两个函数,一个将Tuple编解码器转换为目标类型,另一个函数将其转换为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,3,H,I),BitVector(empty)))

我会鼓励你看Scaladocs而不是在指南,因为Scaladocs有更多的细节.该指南是非常基础的一个很好的开始,但它没有进入组合部分,但是Scaladocs涵盖的很好.

相关文章

共收录Twitter的14款开源软件,第1页Twitter的Emoji表情 Tw...
Java和Scala中关于==的区别Java:==比较两个变量本身的值,即...
本篇内容主要讲解“Scala怎么使用”,感兴趣的朋友不妨来看看...
这篇文章主要介绍“Scala是一种什么语言”,在日常操作中,相...
这篇文章主要介绍“Scala Trait怎么使用”,在日常操作中,相...
这篇文章主要介绍“Scala类型检查与模式匹配怎么使用”,在日...