2012-10-31 13 views
7

Chcę zbudować mały formatator w pythonie, zwracając wartości liczbowe osadzone w liniach ciągów heksadecymalnych.uporządkuj kolejność bajtów w łańcuchu szesnastkowym (python)

Jest to centralna część mojego formatyzatora i powinna być rozsądnie szybka do formatu w tempie ponad 100 linii/s (każda linia około ~ 100 znaków).

Poniższy kod powinien dawać przykład, gdzie jestem obecnie zablokowany.

"data_string_in_orig" pokazuje podany format wejściowy. Musi to być bajt zamieniony na każde słowo. Konieczna jest zamiana z "data_string_in_orig" na "data_string_in_swapped". Koniec końców potrzebuję dostępu do struktury, jak pokazano. Oczekiwany wynik znajduje się w komentarzu.

góry dzięki Wolfgang R

#!/usr/bin/python 

import binascii 
import struct 

## 'uint32 double' 
data_string_in_orig = 'b62e000052e366667a66408d' 
data_string_in_swapped = '2eb60000e3526666667a8d40' 
print data_string_in_orig 

packed_data = binascii.unhexlify(data_string_in_swapped) 
s = struct.Struct('<Id') 
unpacked_data = s.unpack_from(packed_data, 0) 
print 'Unpacked Values:', unpacked_data 

## Unpacked Values: (46638, 943.29999999943209) 

exit(0) 

Odpowiedz

13

array.arrays mają byteswap method:

import binascii 
import struct 
import array 
x = binascii.unhexlify('b62e000052e366667a66408d') 
y = array.array('h', x) 
y.byteswap() 
s = struct.Struct('<Id') 
print(s.unpack_from(y)) 

# (46638, 943.2999999994321) 

h w array.array('h', x) został wybrany, ponieważ określa array.array uważać dane w x w tablicy 2 -Byte szorty. Ważne jest, aby każdy przedmiot był uważany za 2-bajtowy. H, który oznacza 2-bajtowy niepodpisany krótki, działa równie dobrze.

+0

'tablica.byteswap'. Słodkie. Zgaduję, że pójdę dalej i nie opublikuję kludu rozpakowuję big-endian/repack-little-endianowe rozwiązanie, które przygotowywałem ... – Triptych

+0

Śmiało i opublikuj to! Może być przydatny więcej niż jeden sposób rozwiązania problemu. – unutbu

+1

Dzięki, to było szybkie i idealne dla mnie. Przy okazji 100k linii w 5 sek. –

6

Należy to zrobić dokładnie to, co robi unutbu w wersji, ale może być nieco łatwiejsze do naśladowania dla niektórych ...

from binascii import unhexlify 
from struct import pack, unpack 
orig = unhexlify('b62e000052e366667a66408d') 
swapped = pack('<6h', *unpack('>6h', orig)) 
print unpack('<Id', swapped) 

# (46638, 943.2999999994321) 

Zasadniczo rozpakować 6 szorty grubokońcej, zapakować jako 6 szorty little-endian.

Jeszcze raz to samo, co kod unutbu, i powinieneś użyć jego.

edit sobie sprawę mogę używać mojego ulubionego Python idiom za to ... Nie rób tego albo:

orig = 'b62e000052e366667a66408d' 
swap =''.join(sum([(c,d,a,b) for a,b,c,d in zip(*[iter(orig)]*4)],())) 
# '2eb60000e3526666667a8d40' 
0
import binascii, tkinter, array 
from tkinter import * 

infile_read = filedialog.askopenfilename() 

with open(infile, 'rb') as infile_: 
    infile_read = infile_.read() 

x = (infile_read) 
y = array.array('l', x) 
y.byteswap() 
swapped = (binascii.hexlify(y)) 

Jest to 32 bit unsigned short wymiany i osiągnąć kod bardzo podobny do odpowiedzi "unutbu", który jest nieco łatwiejszy do zrozumienia. Technicznie binascii nie jest potrzebny do wymiany. Potrzebna jest tylko tablica.byteswap.

0

Swap z „data_string_in_orig” do „data_string_in_swapped” mogą być również wykonane z listowe bez użycia importu:

>>> d = 'b62e000052e366667a66408d' 
>>> "".join([m[2:4]+m[0:2] for m in [d[i:i+4] for i in range(0,len(d),4)]]) 
'2eb60000e3526666667a8d40' 

Zrozumienie działa na zamianę kolejności bajtów w hex ciągów reprezentujących 16-bitowych słów. Modyfikowanie go dla innej długości słowa jest banalne. Możemy dokonać ogólnej cyfry hex funkcję kolejność wymiany także:

def swap_order(d, wsz=4, gsz=2): 
    return "".join(["".join([m[i:i+gsz] for i in range(wsz-gsz,-gsz,-gsz)]) for m in [d[i:i+wsz] for i in range(0,len(d),wsz)]]) 

params wejściowe są:

d: hex ciąg wejściowy

wsz: słowo-size w przekąski (np.g dla słów 16-bitowych wsz = 4, dla słów 32-bitowych wsz = 8)

gsz: liczba przekąsek, które pozostają razem (np. do zmiany kolejności bajtów gsz = 2, do zmiany kolejności słów 16-bitowych gsz = 4)

Powiązane problemy