Чтение файлов фиксированной ширины в панды с двоичными данными - PullRequest
0 голосов
/ 07 сентября 2018

Я пытаюсь прочитать некоторые данные фиксированной ширины с мэйнфрейма IBM в Pandas. Поля хранятся в смеси EBCDIC, числа сохраняются как двоичные (то есть 255 хранятся как 0xFF), так и двоично-десятичные (то есть 255 хранятся как 0x02FF.). Я знаю длины и типы полей заранее.

Может ли read_fwf иметь дело с такими данными? Есть ли лучшие альтернативы?

Пример - у меня произвольное количество записей, структурированных так, как я пытаюсь прочитать.

import tempfile

databin = 0xF0F3F1F5F1F3F9F9F2F50AC2BB85F0F461F2F061F2F0F1F8F2F0F1F860F0F360F2F360F1F54BF4F54BF5F44BF5F9F2F9F1F800004908

#column 1 -- ten bytes, EBCDIC.  Should be 0315139925.
#column 2 -- four bytes, binary number.  Should be 180534149.
#column 3 -- ten characters, EBCDIC.  Should be 04/20/2018.
#column 4 -- twenty six characters, EBCDIC.  Should be 2018-03-23-15.45.54.592918.
#column 5 -- five characters, packed binary coded decimal.  Should be 4908.  I know the scale ahead of time.

rawbin = databin.to_bytes((databin.bit_length() + 7) // 8, 'big') or b'\0'

with tempfile.TemporaryFile() as fp:
    fp.write(rawbin)

1 Ответ

0 голосов
/ 07 сентября 2018

Я думаю, что, скорее всего, произойдет то, что вам нужно написать что-то, чтобы сделать их запись за записью, я думаю, что вряд ли заставить его работать так, как в пандах, компоненты могут быть разбиты на ( приходится бесстыдно копировать и вставлять Как разбить строку байтов на отдельные байты в python для части BCD):

def bcdDigits(chars):
    for char in chars:
        char = ord(char)
        for val in (char >> 4, char & 0xF):
            if val == 0xF:
                return
            yield val


In [40]: B
Out[40]: b'\xf0\xf3\xf1\xf5\xf1\xf3\xf9\xf9\xf2\xf5\n\xc2\xbb\x85\xf0\xf4a\xf2\xf0a\xf2\xf0\xf1\xf8\xf2\xf0\xf1\xf8`\xf0
\xf3`\xf2\xf3`\xf1\xf5K\xf4\xf5K\xf5\xf4K\xf5\xf9\xf2\xf9\xf1\xf8\x00\x00I\x08'

In [41]: import codecs

In [43]: codecs.decode(B[0:10], "cp500")
Out[43]: '0315139925'

In [44]: int.from_bytes(B[10:14], byteorder='big')
Out[44]: 180534149

In [45]: codecs.decode(B[14:24], "cp500")
Out[45]: '04/20/2018'

In [46]: codecs.decode(B[24:50], "cp500")
Out[46]: '2018-03-23-15.45.54.592918'

In [48]: list(bcdDigits([B[i: i+1] for i in range(50, 54)]))
Out[48]: [0, 0, 0, 0, 4, 9, 0, 8]

Примечание: для последней части, если вы хотите получить взамен целое число:

In [63]: import numpy as np

In [64]: (list(bcdDigits([B[i: i+1] for i in range(50, 54)])) * (10 ** np.arange(8)[::-1])).sum()
Out[64]: 4908
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...