用scala解析二进制数据
我需要解析一些简单的二进制文件。 (这些文件包含n个条目,其中包含几个不同大小的有符号/无符号整数等。)用scala解析二进制数据
在我手动解析的时刻。有人知道一个库可以帮助做这种类型的解析吗?
编辑:“手工”意味着我得到数据字节按字节排序到正确的顺序,并将其转换为一个Int/Byte等。另外一些数据是无符号的。
我以前用过sbinary这个库,它非常好。文件有点稀疏,但我建议先看看旧的wiki page,因为这给你一个起点。然后检查测试规格,因为这给你一些非常好的例子。
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字符,这让我对自己变得更容易一些。我也没有在这个架构上处理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案例类和另一个函数把目标类型,使之成为元组形式:
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,而不是在指南中,因为Scaladocs中有更多的细节。该指南是非常基础的一个良好开端,但它并没有深入到组成部分,但Scaladocs覆盖非常好。
我不知道你的意思是用“手”,但使用简单DataInputStream
(apidoc here)是相当简洁明了什么:
val dis = new DataInputStream(yourSource)
dis.readFloat()
dis.readDouble()
dis.readInt()
// and so on
从另一个SO question摘自:http://preon.sourceforge.net/,它应该是一个框架来做二进制编码/解码..看看它是否有你需要的功能
恩情怎么样?那么pascal字符串(字节大小,然后字符串ascii)呢?我相信他正在寻找类似python的'struct.pack','struct.unpack'。 – 2010-04-19 14:14:25
没有人愿意为像[BMP文件](https://en.wikipedia.org/wiki/BMP_file_format#DIB_header_.28bitmap_information_header.29)这样的真实世界的例子这样做,尤其是当所有数据成员都没有使用时。 – nodakai 2015-12-18 20:59:04
斯卡拉本身没有二进制数据输入库,但java.nio
包做了不错的工作。它没有明确处理未签名的数据 - Java也没有,所以你需要弄清楚你想如何管理它 - 但它确实有方便的“get”方法来考虑字节顺序。
如果有人看到这个,我现在推荐http://scodec.org。与sbinary相同的好处,但更好的支持和更多的功能。 – Aaron 2015-10-05 14:05:17
我仍然不知道如何使用'sbinary'或'scodec'库来解析其他地方定义的二进制协议,即使在通过各自的文档之后,它们也是一系列C结构。你能详细说明一下,最好是用代码片段吗? – nodakai 2015-12-18 20:56:21
我刚刚为C风格的结构添加了scodec解析的示例。希望有所帮助! – Aaron 2015-12-23 02:34:51