Преобразование списка целых чисел в двоичную «строку» в Python - PullRequest
4 голосов
/ 26 августа 2009

У меня есть список номеров, которые я хотел бы отправить на сокетное соединение в виде двоичных данных.

Например, я начинаю со следующего списка:

data = [2,25,0,0,ALPHA,0,23,18,188]

В приведенном выше списке ALPHA может быть любым значением от 1 до 999. Первоначально я преобразовывал это в строку, используя

 hexdata = ''.join([chr(item) for item in data])

Так что, если ALPHA равен 101, это вернет следующую строку:

>>> data = [2,25,0,0,101,0,23,18,188]
>>> hexdata = ''.join([chr(item) for item in data])
>>> hexdata
'\x02\x19\x00\x00e\x00\x17\x12\xbc'

Это прекрасно работает, и '\ x02 \ x19 \ x00 \ x00e \ x00 \ x17 \ x12 \ xbc' - это строка, которую мне нужно отправить.

Однако, это не работает для значений ALPHA, которые превышают 255, потому что это вне диапазона оператора chr. Если бы, например, АЛЬФА было 999, то я хотел бы получить следующую строку:

data = [2,25,0,0,999,0,23,18,188]
hexdata = '\x02\x19\x00\x03\xed\x00\x17\x12\xbc'

Я просматривал документацию по struct.pack (), но не могу понять, как это можно использовать для получения приведенной выше строки. ALPHA - единственная переменная в списке.

Любая помощь будет принята с благодарностью.

РЕДАКТИРОВАТЬ 1

Какое поведение вы хотите? Что-нибудь от 256 до 65535 занимает 2 байта представлять. Вы хотите распаковать его на Обратная сторона? Пожалуйста, обновите пост с вашим намерением. - gahooa 1 мин. Назад

Это правильно, поскольку 999 превышает порог 256, он представлен двумя байтами:

data = [2,25,0,0,999,0,23,18,188]

hexdata = '\x02\x19\x00**\x03\xed**\x00\x17\x12\xbc'

Имеет ли это смысл?

Что касается распаковки, я только отправляю эти данные в сокет, я буду получать данные, но об этом уже позаботились.

РЕДАКТИРОВАТЬ 2

Строка, которую я посылаю, всегда имеет фиксированную длину. Для простоты я думаю, что лучше представить список следующим образом:

ALPHA = 101

data = [25,alpha1,alpha2,1]
hexdata = '\x19\x00e\x01'


ALPHA = 301

data = [25,alpha1,alpha2,1]
hexdata = 'x19\x01\x2d\x01'

как вы можете видеть в строке hexdata, это становится: \ x01 \ x2d \

Если ALPHA <256, alpha1 = 0. </p>

Ответы [ 5 ]

9 голосов
/ 26 августа 2009

Вы хотите отправить один байт для ALPHA, если он <256, но два байта, если> = 256? Это кажется странным - как получатель узнает, в чем дело ... ???

Но, если это то, что вы хотите, то

x = struct.pack(4*'B' + 'HB'[ALPHA<256] + 4*'B', *data)

- один из способов достижения этого.

5 голосов
/ 26 августа 2009

Если вы заранее знаете данные и позицию ALPHA, лучше использовать struct.pack с прямым порядком байтов для этой позиции и пропустить 0, который может быть перезаписан:

def output(ALPHA):
    data = [2,25,0,ALPHA,0,23,18,188]
    format = ">BBBHBBBB"
    return struct.pack(format, *data)
output(101) # result: '\x02\x19\x00\x00e\x00\x17\x12\xbc'
output(999) # result: '\x02\x19\x00\x03\xe7\x00\x17\x12\xbc'
3 голосов
/ 26 августа 2009

Вы можете использовать Python массив

import array
a = array.array('i')
a.extend([2,25,0,0,101,0,23,18,188])
output = a.tostring()
1 голос
/ 26 августа 2009

Байты не могут иметь значение больше 255, поэтому если ALPHA больше 255, вам придется как-то разделить его на два байта. Это можно сделать так:

high, low  = divmod(ALPHA, 255)

Затем вы можете вставить максимум и минимум в список значений.

Существуют и другие варианты, такие как использование bytearray (в 2.6) или struct.pack и т. Д., Но в конце вам придется каким-то образом преобразовать это число два в два байта.

0 голосов
/ 06 июня 2013

Вы хотите отправить один байт для ALPHA, если он <256, но два байта, если> = 256?

другой (возможно, более общий) способ будет:

x = reduce(lambda x, y: x + y, map(lambda x: struct.pack('B', x), data))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...