Scala - UTF8字符串的字节数组

时间:2014-12-17 04:22:54

标签: scala

我有一个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将大于零。

3 个答案:

答案 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)

考虑定义heremultiSpan方法,这是span在给定列表上的重复应用,

z.multiSpan(_ == 0).map( _.drop(2).map(_.toChar).mkString )

这里的跨越条件是项是否等于0,然后我们删除前两个前缀字节,并将剩余的转换为String

注意关于使用multiSpan,请回忆import annotation.tailrec