Manipularea datelor binare în Python

Deschid un fișier binar astfel:

file = open("test/test.x", 'rb')

și citind în rânduri la o listă. Fiecare linie arată un pic ca:

'\xbe\x00\xc8d\xf8d\x08\xe4.\x07~\x03\x9e\x07\xbe\x03\xde\x07\xfe\n'

Îmi este greu să manipulez aceste date. Dacă încerc să imprim fiecare linie, python se blochează și emite zgomote bip (cred că există un cod binar de bip acolo undeva). Cum pot folosi aceste date în siguranță? Cum pot converti fiecare număr hexadecimal în zecimal?


person Dominic Bou-Samra    schedule 17.06.2010    source sursă


Răspunsuri (7)


Pentru a o imprima, puteți face ceva de genul acesta:

print repr(data)

Pentru toată treaba ca hex:

print data.encode('hex')

Pentru valoarea zecimală a fiecărui octet:

print ' '.join([str(ord(a)) for a in data])

Pentru a despacheta numere întregi binare etc. din date ca și cum ar fi provenit inițial dintr-o structură în stil C, uitați-vă la struct.

person ʇsәɹoɈ    schedule 17.06.2010
comment
Mulțumesc! Asta cautam! - person Dominic Bou-Samra; 17.06.2010

\xhh este caracterul cu valoarea hexadecimal hh. Alte caractere precum . și `~' sunt caractere normale.

Iterarea pe un șir vă oferă caracterele din el, unul câte unul.

ord(c) va returna un număr întreg reprezentând caracterul. De exemplu, ord('A') == 65.

Aceasta va imprima numerele zecimale pentru fiecare caracter:

s = '\xbe\x00\xc8d\xf8d\x08\xe4.\x07~\x03\x9e\x07\xbe\x03\xde\x07\xfe\n'
print ' '.join(str(ord(c)) for c in s)
person Jon-Eric    schedule 17.06.2010
comment
Rețineți că \x07 este acel caracter ASCII BEL. Acesta este ceea ce provoacă bipurile. - person dan04; 17.06.2010

Datele binare sunt rareori împărțite în „linii” separate prin „\n”. Dacă este, va avea un mecanism de evadare implicit sau explicit pentru a distinge între „\n” ca terminator de linie și „\n” ca parte a datelor. Citirea orbește a unui astfel de fișier sub formă de linii fără a cunoaște mecanismul de evadare este inutilă.

Pentru a răspunde preocupărilor dvs. specifice:

„\x07” este caracterul ASCII BEL, care a fost inițial pentru a suna clopoțelul pe o mașină de teletip.

Puteți obține valoarea întreagă a unui octet „b” făcând ord(b).

CU toate acestea, pentru a procesa corect datele binare, trebuie să știți care este aspectul. Puteți avea numere întregi semnate și fără semn (de dimensiuni 1, 2, 4, 8 octeți), numere cu virgulă mobilă, numere zecimale de lungimi diferite, șiruri de lungime fixă, șiruri de lungime variabilă etc. Complicația adăugată vine de la înregistrarea datelor. în mod bigendian sau littleendian fashion. Odată ce cunoașteți toate cele de mai sus (sau aveți ipoteze foarte bine informate), modulul struct Python ar trebui să poată fi utilizat pentru întreaga sau cea mai mare parte a prelucrării dumneavoastră; modulul ctypes poate fi de asemenea util.

Formatul de date are un nume? Dacă da, spuneți-ne; este posibil să vă putem îndruma către cod sau documente.

Vă întrebați „Cum pot folosi aceste date în siguranță?” ceea ce ridică întrebarea: la ce vrei să-l folosești? Ce manipulări vrei să faci?

person John Machin    schedule 17.06.2010

După cum a menționat theatrus, ord și hex te-ar putea ajuta. Dacă doriți să încercați să interpretați un fel de date binare structurate din fișier, struct modulul ar putea fi de ajutor.

person Mattias Nilsson    schedule 17.06.2010
comment
+1 pentru struct. Calea corectă de a interpreta datele binare împachetate. - person Noufal Ibrahim; 17.06.2010

Încercați să imprimați datele convertite în caractere ASCII, ceea ce nu va funcționa.

Puteți utiliza în siguranță orice octet al datelor. Dacă doriți să o imprimați ca hexazecimal, uitați-vă la funcțiile ord și hex/

person Yann Ramin    schedule 17.06.2010

Folosești read() sau readline()? Ar trebui să utilizați read(n) pentru a citi n octeți; readline() va citi până când atinge o linie nouă, pe care fișierul binar ar putea să nu o aibă.

În orice caz, totuși, vi se returnează un șir de octeți, care pot fi caractere imprimabile sau neprintabile și probabil că nu este foarte util.

Ceea ce doriți este ord(), care convertește un șir de un octet în valoarea întreagă corespunzătoare. read() din fișier câte un octet și apelați ord() pe rezultat sau repetarea întregului șir.

person Paul Richter    schedule 17.06.2010

Dacă sunteți dispus să utilizați NumPy și bitstream, puteți face

>>> from numpy import *
>>> from bitstream import BitStream
>>> raw = '\xbe\x00\xc8d\xf8d\x08\xe4.\x07~\x03\x9e\x07\xbe\x03\xde\x07\xfe\n'
>>> stream = BitStream(raw)
>>> stream.read(raw, uint8, len(stream) // 8)
array([190,   0, 200, 100, 248, 100,   8, 228,  46,   7, 126,   3, 158,
         7, 190,   3, 222,   7, 254,  10], dtype=uint8)
person Sébastien Boisgérault    schedule 13.05.2018