UTF8字符串的Scala字节数组

UTF8字符串的Scala字节数组,scala,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') 我想将其转换为字符串列表,因此它应该类似于列表(“ABC”、“DEFGH”、“I”) 有没有一种优雅的方法可以做到这一点 (编辑)这些字符串不是以null结尾的,您在数组中看到的0只是M

我有一个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')
我想将其转换为字符串列表,因此它应该类似于
列表(“ABC”、“DEFGH”、“I”)

有没有一种优雅的方法可以做到这一点


(编辑)这些字符串不是以null结尾的,您在数组中看到的0只是MSB。如果字符串足够长,MSB将大于零。

编辑:根据注释中的说明更新,前2个字节定义了一个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()
  }
}
def转换(bs:List[Byte]):List[String]={
bs匹配{
案例计数\u b1::计数\u b2::t=>
val计数=((计数b1&0xff)列表()
}
}

调用convert(z.toList)这是我用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)
  }
})

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

z.multiSpan(_ == 0).map( _.drop(2).map(_.toChar).mkString )
这里的扩展条件是一个项是否等于
0
,然后我们删除前两个前缀字节,并将剩余的转换为
字符串


注意在使用
multiSpan
时,请回想一下导入注释.tailrec

谢谢。我会尝试一下。为什么您认为字符串以null结尾?数组中的0只是长度的MSB。除非我遗漏了什么。现在我得到了它。长度部分由2个字节组成!那么我的解决方案将不可用工作。我看到其他人也认为数组中的零是分隔符。很抱歉,我在问题中添加了一个小的澄清,以供将来参考。谢谢。似乎这个版本的伸缩性很差。在我的基准测试中,它相当于下面Lionel的版本,在大约10000次小迭代中(66ms vs 68ms)当我把它推到100000时,速度会慢2倍多(180毫秒对340毫秒)。它会逐渐变小(在1米时,我得到1191毫秒对2943毫秒)。谢谢。正如下面在另一个回答中与Suztomo讨论的,它不考虑MSB/LSB前缀。这些字符串不是以null结尾的。我只是碰巧将MSB设置为0,这样我就不必发布带有大字符串的数组。谢谢。这些字符串不是以null结尾的,很抱歉造成混淆。通过按位操作?在我的代码中,我做了一些类似count=(buff(1)和0xff)|((buff(0)和0xff)的操作是的。我比较喜欢ByteBuffer,因为它更易于阅读,但我想如果你将它封装在像bytes2int这样的函数中,它也会有同样的效果。酷。我还使用递归尾函数构建了自己的解决方案(正如下面酶的链接所暗示的)现在我需要找出一个好的基准测试方法,看看哪一个是最好的。因为我在处理网络数据包,所以我对性能很敏感。仅供参考,分配版本的10000次迭代花费了180ms,咬合操作版本花费了61ms。现在我将尝试修复一些其他版本以进行尝试
z.multiSpan(_ == 0).map( _.drop(2).map(_.toChar).mkString )