Разбор двоичных файлов, которые содержат значения BCD (Binary Coded Decimal) с использованием Python Numpy - PullRequest
0 голосов
/ 21 ноября 2018

У меня есть двоичный файл, некоторые поля которого закодированы как BCD (Binary Coded Decimal).Пример как показано ниже.

14 75 26 58 87 7F (необработанные байты в шестнадцатеричном формате).

Я использую (np.void, 6) для чтения и преобразования из двоичного файла, а ниже:выходной я получаю.

b '\ x14 \ x75 \ x26 \ x58 \ x87 \ x7F'

Но я бы хотел получить вывод как '14752658877', без символа заполнения 'F', используя numpy.

Ниже приведен код: с открытым (имя файла, "rb") как f:

    while True:

        chunk = f.read(chunksize)

        if (chunk):

            dt = np.dtype([('a','b'), ('b', '>i4'), ('c', 'S15'),('d', np.str, 7),
                                   ('e', 'S7'), ('f', np.void, 6)])

            x = np.frombuffer (chunk, dtype=dt)
            print (x)

        else:
            break

Кроме того, входной файл содержит много двоичных записей фиксированной длины.Каков эффективный способ конвертировать и хранить его как файл ascii, используя numpy.

1 Ответ

0 голосов
/ 22 ноября 2018

Я не знаю, может ли numpy как-то ускорить это, но можно быстро создать специальную функцию:

fastDict = {16*(i//10)+(i%10):i for i in range(100)}

def bcdToInteger(bcd):
    result = 0
    while bcd and bcd[0] in fastDict:
        result *= 100
        result += fastDict[bcd[0]]
        bcd = bcd[1:]
    if bcd and bcd[0] & 0xf0 <= 0x90:
        result *= 10
        result += bcd[0]>>4
        if bcd[0] & 0xf <= 9:
            result *= 10
            result += bcd[0] & 0x0f
    return result

>>> print (bcdToInteger(b'\x14\x75\x26\x58\x87\x7F'))  # your sequence
14752658877
>>> print (bcdToInteger(b'\x12\x34\xA0'))   # first invalid nibble ends
1234
>>> print (bcdToInteger(b'\x00\x00\x99'))   # and so does an end of string
99
>>> print (bcdToInteger(b'\x1F'))           # a single nibble value
1

Пока вы продолжаете кормить его действительными байтами BCD, он умножает результат на 100и добавляет две новые цифры.Только последний байт нуждается в некотором дополнительном осмотре: если верхний полубайт действителен, результат до сих пор умножается на 10, и этот полубайт добавляется.Если допустим и самый низкий клев, это повторяется.

fastDict - для ускорения.Это словарь, который возвращает правильное значение для всех 100 шестнадцатеричных байтов от 00 до 99, поэтому число фактических вычислений будет как можно меньше.Вы можете обойтись без словаря, но это означает, что вы должны выполнять сравнения и вычисления в блоке if для каждого байта.

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