我有一个UTF8字符串的字节数组(或更确切地说是ByteString),它们的长度前缀为2字节(msb,lsb)。例如:
val z = akka.util.ByteString(0, 3, 'A', 'B', 'C', 0, 5,
'D', 'E', 'F', 'G', 'H',0,1,'I')
我想将其转换为字符串列表,因此它应该类似于List("ABC", "DEFGH", "I")
。
有优雅的方法吗?
(编辑)这些字符串不是空终止的,你在数组中看到的0只是MSB。如果字符串足够长,则MSB将大于零。
答案 0 :(得分:1)
编辑:基于前两个字节定义int的注释中的说明进行了更新。所以我手动转换了它。
def convert(bs: List[Byte]) : List[String] = {
bs match {
case count_b1 :: count_b2 :: t =>
val count = ((count_b1 & 0xff) << 8) | (count_b2 & 0xff)
val (chars, leftover) = t.splitAt(count)
new String(chars.toArray, "UTF-8") :: convert(leftover)
case _ => List()
}
}
致电convert(z.toList)
答案 1 :(得分:0)
这是我对foldLeft的回答。
def convert(z : ByteString) = z.foldLeft((List() : List[String], ByteString(), 0, 0))((p, b : Byte) => {
p._3 match {
case 0 if p._2.nonEmpty => (p._2.utf8String :: p._1, ByteString(), -1, b.toInt)
case 0 => (p._1, p._2, -1, b.toInt)
case -1 => (p._1, p._2, (p._4 << 8) + b.toInt, 0)
case _ => (p._1, p._2 :+ b, p._3 - 1, 0)
}
})
它的工作原理如下:
scala> val bs = ByteString(0, 3, 'A', 'B', 'C', 0, 5, 'D', 'E', 'F', 'G', 'H',0,1,'I')
scala> val k = convert(bs); (k._2.utf8String :: k._1).reverse
k: (List[String], akka.util.ByteString, Int, Int) = (List(DEFGH, ABC),ByteString(73),0,0)
res20: List[String] = List(ABC, DEFGH, I)
答案 2 :(得分:0)
考虑定义here的multiSpan
方法,这是span
在给定列表上的重复应用,
z.multiSpan(_ == 0).map( _.drop(2).map(_.toChar).mkString )
这里的跨越条件是项是否等于0
,然后我们删除前两个前缀字节,并将剩余的转换为String
。
注意关于使用multiSpan
,请回忆import annotation.tailrec
。