我需要解析一些简单的二进制文件. (文件包含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涵盖的很好.