您可以使用Scala Pickling或POF或谷歌的Protobuf,但如果你的格式是如此的限制,最簡單的方法就是寫你自己的序列:
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
或者你可以使用Scodec庫(此選項是更好因爲你將不得不自然而然值範圍檢查):
SBT:
libraryDependencies += "org.typelevel" %% "scodec-core" % "1.3.0"
編解碼器:
case class Data(magicNumber: Int, version: Int, payload: ByteVector)
val codec = (uint(4) :: uint(1) :: variableSizeBytes(uint(3), bytes)).as[Data]
用途:
val encoded = codec.encode(Data(2, 1, bin"01010101".bytes)).fold(sys.error, _.toByteArray)
val decoded = codec.decode(BitVector(encoded)).fold(sys.error, _._2)
謝謝,這有助於。我也試圖看看斯卡拉酸洗,但不幸的是它缺乏示例。我還不知道如何用酸洗/取出來做。現在,這對我來說已經足夠了! – 2014-09-19 15:25:08
scodec比酸洗更加面向位,我已經用它的工作示例更新了答案。但它取決於像scalaz這樣的重型圖書館,不成形。 – dk14 2014-09-19 21:08:57
我正在做對嗎?我似乎無法進行往返:val input2 = new Data(0,3,Array [Byte]('h','e','l','l','o')) val output2 = serialize(Stream(input2)) val output3 =反序列化(輸出2) – 2014-09-20 05:30:05