将字节数组从 \xff 转换为 x0FF

1 投票
1 回答
986 浏览
提问于 2025-04-20 19:55

我正在用Python 3写一段代码,目的是从心电图传感器读取数据。最终的代码需要把从传感器收到的数据包写入一个文件中。

这是我现在写的代码:

import serial


if __name__ == '__main__':
    buffer = [0, 0, 0, 0, 0, 0]
    f = open('dumpECG', 'w')
    print("Hi")
    ser = serial.Serial('/dev/ttyUSB0', 115200)
    while 1 == 1:
        while ser.inWaiting() > 6:
            buf = ser.read()
            if buf > b'\xf7':

                if buf == b'\xfd':
                    1 == 1
                else:
                    buffer[0] = buf
                    if ser.isOpen():
                        buffer[1] = ser.read()
                    if buffer[0] == b'\xf8':
                        temp = (ord(buffer[1]) >> 4) + 2
                        if temp < 11:
                            for i in range(2, int(temp), 1):
                                if ser.isOpen():
                                    buffer[i] = ser.read()
                            print(buffer)
                            data = ''.join(str(e) for e in buffer)
                            data = map(hex, map(ord, data))
                            f.write(''.join(data))
                            f.write("\n")
                    elif buffer[0] == b'\xfe':
                        temp = (ord(buffer[1]) >> 4) + 2
                        if temp < 8:
                            for i in range(2, int(temp), 1):
                                if ser.isOpen():
                                    buffer[i] = ser.read()
                            print(buffer)
                            f.write(''.join(str(e) for e in buffer))
                            f.write("\n")
                    elif buffer[0] == b'\xf9' or buffer[0] == b'\xfa':
                        if ser.isOpen():
                            buffer[2] = ser.read()
                        print(buffer)
                        f.write(''.join(str(e) for e in buffer))
                        f.write("\n")
                    elif buffer[0] == b'\xfc':
                        for i in range(2, int(6), 1):
                            if ser.isOpen():
                                buffer[i] = ser.read()
                        f.write(''.join(str(e) for e in buffer))
                        f.write("\n")

作为示例数据,当我第一次打印(buffer)时,buffer里面的内容是:"[b'\xf8', b'8', b'\x80', b'\x80', b'\x80', 0]",我需要把它写成文件里的"0xF8, 0x38, 0x80, 0x80, 0x80, 0"。

我尝试过这样做:

data = ''.join(str(e) for e in buffer)
data = map(hex, map(ord, data))

但是它把所有字符都转换了,而不是我想要的数值。

1 个回答

1

你现在有这样的内容:

"[b'\xf8', b'8', b'\x80', b'\x80', b'\x80', 0]" 

而你想要的是这样的:

"0xF8, 0x38, 0x80, 0x80, 0x80, 0"

(我假设你其实想要的是 0x38,而不是 0x08,因为 b'8' 对应的是 b'\x38',而不是 b'\x08'。如果我理解错了,你需要解释一下你的规则……)


首先要注意的是,这显然是 Python 的 repr 函数生成的输出,因为没有其他常见的方法会给你这些以 b 开头的字符串。如果可能的话,最好是修改生成这些字符串的代码,让它直接传递列表(如果在 Python 内部)或者使用一些标准、安全、可靠的交换格式,比如 JSON,而不是直接打印 repr 的结果。但如果你不能改变这一点,那么反向操作的方法就是使用 ast.literal_eval

>>> ast.literal_eval(buffer)
[b'\xf8', b'8', b'\x80', b'\x80', b'\x80', 0]

接下来,这些值中有些是单字节的 bytes 对象,有些是数字。看起来你想保留数字不变,但把字节转换成十六进制数字。所以,我们需要对每种类型做不同的处理。

那么我们该如何处理每种类型呢?对于 bytes,我们需要调用 ord(或者直接用 [0]),然后再用 hex,这正是你想做的。但对于 int,我们只需要调用 str。所以:

>>> [hex(ord(b)) if isinstance(b, bytes) else str(b) 
...  for b in ast.literal_eval(buffer)]
['0XF8', '0X38', '0X80', '0X80', '0X80', '0']

现在我们只需要把它们连接起来:

>>> ', '.join(hex(ord(b)) if isinstance(b, bytes) else str(b) 
...           for b in ast.literal_eval(buffer))
'0xf8, 0x38, 0x80, 0x80, 0x80, 0'

如果你真的需要字母的十六进制数字是大写的,hex 是做不到的,所以:

>>> ', '.join('0x{:2X}'.format(ord(b)) if isinstance(b, bytes) else str(b) 
...           for b in ast.literal_eval(buffer))
'0xF8, 0x38, 0x80, 0x80, 0x80, 0'

撰写回答