从scala中的字节数组中解析固定长度字段的最快方法?

时间:2011-04-22 21:47:49

标签: performance scala

在Scala中,我收到一条UDP消息,最后得到一个DatagramPacket,其缓冲区包含包含该消息的Array [Byte]。此消息是所有ASCII字符,是完全固定长度的字段,其中一些是数字,其他单个字符或字符串。从消息数据中解析这些字段的最快方法是什么?

例如,假设我的消息具有以下格式:

2 bytes - message type, either "AB" or "PQ" or "XY"
1 byte - status, either a, b, c, f, j, r, p or 6
4 bytes - a 4-character name
1 byte - sign for value 1, either space or "-"
6 bytes - integer value 1, in ASCII, with leading spaces, eg. "  1234"
1 byte - sign for value 2
6 bytes - decimal value 2

所以消息可能看起来像

ABjTst1 5467- 23.87

消息类型“AB”,状态“j”,名称“Tst1”,值1是5467,值2是-23.87

到目前为止我所做的是获取数组message: Array[Byte],然后从中获取切片, 比如

val msgType= new String(message.slice(0, 2))
val status = message(2).toChar
val name = new String(message.slice(3, 7))
val val1Sign = message(7).toChar
val val1= (new String(message.slice(8, 14)).trim.toInt * (if (val1Sign == '-') -1 else 1))
val val2Sign = message(14).toChar
val val2= (new String(message.slice(15, 21)).trim.toFloat * (if (val2Sign == '-') -1 else 1))

当然,重用的功能,例如解析数字,通常会进入函数。

这种技术很简单,但如果速度很重要,有没有更好的方法呢?

2 个答案:

答案 0 :(得分:2)

编写自己的字节数组到基元的转换会稍微提高速度(如果你真的需要速度),因为它会避免产生额外的String对象。此外,您应该使用String构造函数

而不是切片数组(需要您创建另一个数组)
String(byte[] bytes, int offset, int length)

避免制作额外的副本。

答案 1 :(得分:0)

我没有进行性能测试的数据,但也许你有?您是否尝试使用预编译模式进行模式匹配?

评论中的数字列举了与小组相对应的开始数据:

//                              12     3   4    5           6     7     8                 9     10
val pattern = Pattern.compile ("((AB)|(PQ)|(XY))([abcfjrp6])(.{4})([- ])( {0,6}[0-9]{0,6})([- ])([ 0-9.]{1,6})")
// 
def msplit (message: String) = {
  val matcher = pattern.matcher (message) 
  if (matcher.find ())
    List (1, 5, 6, 7, 8, 9, 10).foreach (g => println (matcher.group(g)))
}

val s = "ABjTst1 5467- 23.87"
msplit (s)

模式/匹配器当然是Javaland - 也许你会找到一个带有“...”的更多scala-way解决方案.r

结果:

AB
j
Tst1

5467
-
 23.87
相关问题