Come si leggono i byte dal file in Python
Domanda
Simile a questa domanda, sto provando a letto nell'intestazione di un tag ID3v2 e ho difficoltà a capire come ottenere singoli byte in Python.
Ho prima letto tutti i dieci byte in una stringa. Voglio quindi analizzare le singole informazioni.
Posso prendere i due caratteri del numero di versione nella stringa, ma poi non ho idea di come prendere quei due caratteri e ricavarne un intero.
Il pacchetto struct sembra essere quello che voglio, ma non riesco a farlo funzionare.
Ecco il mio codice finora (sono molto nuovo su Python tra l'altro ... quindi prenditela comoda con me):
def __init__(self, ten_byte_string):
self.whole_string = ten_byte_string
self.file_identifier = self.whole_string[:3]
self.major_version = struct.pack('x', self.whole_string[3:4]) #this
self.minor_version = struct.pack('x', self.whole_string[4:5]) # and this
self.flags = self.whole_string[5:6]
self.len = self.whole_string[6:10]
La stampa di qualsiasi valore tranne ovviamente è una merda perché non sono formattati correttamente.
Soluzione
Se si dispone di una stringa, con 2 byte che si desidera interpretare come un numero intero a 16 bit, è possibile farlo tramite:
>>> s = '\0\x02'
>>> struct.unpack('>H', s)
(2,)
Nota che > è per big-endian (la parte più grande dell'intero viene prima). Questo è il formato utilizzato dai tag id3.
Per altre dimensioni di numeri interi, si utilizzano codici di formato diverso. per esempio. & Quot; " per un numero intero a 32 bit con segno. Consulta la guida (struct) per i dettagli.
Puoi anche decomprimere più elementi contemporaneamente. ad es. per 2 short senza segno, seguito da un valore con segno a 32 bit:
>>> a,b,c = struct.unpack('>HHi', some_string)
Seguendo il tuo codice, stai cercando (in ordine):
- una stringa di 3 caratteri
- 2 valori a byte singolo (versione principale e secondaria)
- una variabile flag da 1 byte
- una quantità di lunghezza di 32 bit
La stringa di formato per questo sarebbe:
ident, major, minor, flags, len = struct.unpack('>3sBBBI', ten_byte_string)
Altri suggerimenti
Sto cercando di leggere un'intestazione del tag ID3v2
FWIW, c'è già un modulo per questo.
Stavo per raccomandare il pacchetto struct
ma poi hai detto di averlo provato. Prova questo:
self.major_version = struct.unpack('H', self.whole_string[3:5])
La funzione pack ()
converte i tipi di dati Python in bit e la funzione unpack ()
converte i bit in tipi di dati Python.