2012-01-11 23 views
12

Sto lavorando con Python3.2. Devo prendere un flusso esadecimale come input e analizzarlo a livello di bit. Così ho usatoConverti byte in bit in python

bytes.fromhex(input_str)

per convertire la stringa di byte effettivi. Ora come posso convertire questi byte in bit?

+1

I byte sono bit, solo 8 alla volta;) - La risposta dipende da ciò che si vuole fare, per favore sii più specifico Anche la manipolazione dei bit avviene principalmente a livello di byte ... –

+0

Voglio rappresentare i byte in la forma un po 'stringa in modo che io possa fare qualcosa del tipo: field1 = bit_string [0: 1] field2 = bit_string [1:16] e così via – user904832

risposta

10

E qualcosa di simile?

>>> bin(int('ff', base=16)) 
'0b11111111' 

Questo convertirà la stringa esadecimale è necessario un intero e che intero in una stringa in cui ogni byte è impostato su 0/1 a seconda del bit valore del numero intero.

Come sottolineato da un commento, se avete bisogno di sbarazzarsi del prefisso 0b, si può fare in questo modo:

>>> bin(int('ff', base=16)).lstrip('0b') 
11111111 

o in questo modo:

>>> bin(int('ff', base=16))[2:] 
11111111 
+0

lstrip (' - 0b ') # rimuovi zeri iniziali e segno meno – ahoffer

+0

@ahoffer Grazie per il tuo commento. Ho aggiornato la mia risposta per far sapere all'OP come rimuovere il prefisso '0b'. – jcollado

+4

Si noti che 'lstrip ('0b')' rimuoverà, per esempio, '00bb' dato che l'argomento di' lstrip' è un * set * di caratteri da rimuovere. In questo caso funzionerà bene, ma preferisco la soluzione '[2:]' poiché è più esplicita. –

14

operazioni sono molto più più veloce quando lavori a livello intero. In particolare, la conversione in una stringa come suggerito qui è molto lenta.

Se si desidera solo il bit 7 e 8, utilizzare ad es.

val = (byte >> 6) & 3 

(questo è:. Spostare il byte 6 bit verso destra - rilasciandoli poi mantenere soltanto gli ultimi due bit 3 è il numero con i primi due bit impostati ...)

Questi possono facilmente traducibile in semplici operazioni della CPU che sono super veloci.

23

Un altro modo per farlo è quello di utilizzare il modulo bitstring:

>>> from bitstring import BitArray 
>>> input_str = '0xff' 
>>> c = BitArray(hex=input_str) 
>>> c.bin 
'0b11111111' 

E se è necessario mettere a nudo il principale 0b:

>>> c.bin[2:] 
'11111111' 

Il modulo bitstring non è un requisito, come jcollado mostra la risposta, ma ha molti metodi performanti per trasformare l'input in bit e manipolarli. Si potrebbe trovare questo a portata di mano (o non), ad esempio:

>>> c.uint 
255 
>>> c.invert() 
>>> c.bin[2:] 
'00000000' 

ecc

+1

+1. E per l'ultima versione di bitstring (3.0) non è necessario rimuovere il principale '0b'. –

4

Per binario:

bin(byte)[2:].zfill(8) 
+0

Non è possibile convertire un byte usando bin. – user3467349

3

penso più semplice sarebbe l'uso numpy qui.Per esempio si può leggere un file come byte e quindi espandere a pezzi facilmente in questo modo:

Bytes = numpy.fromfile(filename, dtype = "uint8") 
Bits = numpy.unpackbits(Bytes) 
1

Usa ord durante la lettura di byte di lettura:

byte_binary = bin(ord(f.read(1))) # Add [2:] to remove the "0b" prefix 

O

Uso str.format():

'{:08b}'.format(ord(f.read(1))) 
0

Ecco come per farlo utilizza format()

print "bin_signedDate : ", ''.join(format(x, '08b') for x in bytevector) 

E 'importante il 08b. Ciò significa che saranno aggiunti un massimo di 8 zeri iniziali per completare un byte. Se non lo specifichi, il formato avrà solo una lunghezza di bit variabile per ogni byte convertito.

0

Le altre risposte qui forniscono i bit in ordine big-endian ('\x01' diventa '00000001')

Nel caso siate interessati al fine little-endian di bit, che è utile in molti casi, come rappresentazioni comuni di bignum ecc - ecco un frammento per questo:

def bits_little_endian_from_bytes(s): 
    return ''.join(bin(ord(x))[2:].rjust(8,'0')[::-1] for x in s) 

E per l'altra direzione:

def bytes_from_bits_little_endian(s): 
    return ''.join(chr(int(s[i:i+8][::-1], 2)) for i in range(0, len(s), 8))