Самый быстрый способ разобрать поля фиксированной длины из байтового массива в Scala? - PullRequest
3 голосов
/ 23 апреля 2011

В Scala я получаю сообщение UDP и в итоге получаю DatagramPacket, в буфере которого находится массив [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 ]

2 голосов
/ 23 апреля 2011

Запись ваших собственных преобразований байтовый массив в примитив несколько улучшит скорость (если вы действительно нуждаетесь в скорости), поскольку это позволит избежать создания дополнительного String объекта. Кроме того, вместо нарезки массива (который требует создания другого массива), вы должны использовать конструктор String

String(byte[] bytes, int offset, int length)

, что исключает создание дополнительной копии.

0 голосов
/ 23 апреля 2011

У меня нет данных для тестирования производительности, но, может быть, у вас есть?Вы пробовали сопоставление с шаблоном с предварительно скомпилированным шаблоном?

Числа в комментарии перечисляют открывающие парены, которые соответствуют группам:

//                              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)

Pattern / Matcher - это, конечно, Javaland -может быть, вы найдете более подходящее решение с помощью "...". r

Результат:

AB
j
Tst1

5467
-
 23.87
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...