首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Scala位字段序列化

Scala位字段序列化
EN

Stack Overflow用户
提问于 2014-09-19 03:27:01
回答 2查看 518关注 0票数 3

我在Scala非常新,我对位操作特性感到困惑。我希望有人能给我指明正确的方向?

我使用以下位字段定义了一个字节数组:

代码语言:javascript
运行
复制
0-3 - magic number
  4 - version
5-7 - payload length in bytes
8-X - payload, of variable length, as indicated in bits 5-7

我想将它来回序列化到一个结构中,例如:

代码语言:javascript
运行
复制
MagicNumber: Integer
Version: Integer
Length: Integer
payload: Array[Byte]

在这种情况下,如何以最佳方式处理比特呢?我看到的大多数示例都涉及更高级别的序列化,例如JSON。在本例中,我试图序列化和反序列化TCP二进制数据。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-09-19 04:54:07

您可以使用鱿鱼腌制、POF或Google,但如果您的格式受到如此限制,最简单的方法是编写您自己的序列化程序:

代码语言:javascript
运行
复制
case class Data(magicNumber: Int, version: Int, payload: Array[Byte])

def serialize(data: Stream[Data]): Stream[Byte] = 
   data.flatMap(x => 
     Array((x.magicNumber << 4 | x.version << 3 | x.payload.length).toByte) ++ x.payload)

@scala.annotation.tailrec
def deserialize(binary: Stream[Byte], acc: Stream[Data] = Stream[Data]()): Stream[Data] =   
   if(binary.nonEmpty) {
     val magicNumber = binary.head >> 4 
     val version = (binary.head & 0x08) >>3 
     val size = binary.head & 0x07
     val data = Data(magicNumber, version, ByteVector(binary.tail.take(size).toArray)) 
     deserialize(binary.drop(size + 1), acc ++ Stream(data)) 
   } else acc

或者您可以使用苏格兰人库(这个选项更好,因为您将进行自动值范围检查):

Sbt:

代码语言:javascript
运行
复制
  libraryDependencies += "org.typelevel" %% "scodec-core" % "1.3.0"

编解码器:

代码语言:javascript
运行
复制
  case class Data(magicNumber: Int, version: Int, payload: ByteVector)
  val codec = (uint(4) :: uint(1) :: variableSizeBytes(uint(3), bytes)).as[Data]

使用:

代码语言:javascript
运行
复制
  val encoded = codec.encode(Data(2, 1, bin"01010101".bytes)).fold(sys.error, _.toByteArray)
  val decoded = codec.decode(BitVector(encoded)).fold(sys.error, _._2)
票数 7
EN

Stack Overflow用户

发布于 2014-09-19 05:47:02

我会看看记分。基于UDP示例,它应该类似于(未经测试):

代码语言:javascript
运行
复制
import scodec.bits.{ BitVector, ByteVector }
import scodec.codecs._

case class Datagram(
  magicNumber: Int,
  version: Byte,
  payload: ByteVector)

object Datagram {
  implicit val codec: Codec[Datagram] = {
    ("magic_number" | int32 ) ::
    ("version" | byte ) ::
    variableSizeBytes(int(3),
      ("payload" | bytes ))
  }.as[Datagram]
}
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/25925900

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档