I have a binary hex string, for example: b'\x914\x05\x11\x11\x95h\xf5'
(the f
is a filler in this case), and the expected result would be b'\x914\x05\x11\x11\x95h\xf5'
→ 91340511119568F5
→ 19435011115986515
.
To do this with the string and a loop is probably not the best solution (there are million on records), what would be a better way?
Edit: Forgot to mention the f is just a filler added from the server (network switch) to provide an even number for the switching (as mentioned by mkrieger)
CodePudding user response:
What you have is a bytes
object. When iterating over it you get integer values:
>>> s = b'\x914\x05\x11\x11\x95h\xf5'
>>> list(s) # equivalent to [b for b in s]
[145, 52, 5, 17, 17, 149, 104, 245]
To swap the two "nibbles" (the two 4-bit halves) of a byte, you can use bitwise operations, given that the byte is represented by its integer value. To select the higher-valued nibble, use a bit mask 0xF0
with bitwise and (&
), and to select the lower-valued nibble, use 0x0F
. Then shift them by 4 bits in the respective directions and combine them again with bitwise or (|
):
def swap_nibbles(b: int) -> int:
return ((b & 0xF0) >> 4) | ((b & 0x0F) << 4)
Now you can do this for all bytes in s
to get a list of byte values with swapped nibbles:
>>> swapped_nibbles = [swap_nibbles(b) for b in s]
# [25, 67, 80, 17, 17, 89, 134, 95]
Now you just need to reassemble these numbers to your desired result. I'm not entirely sure what exactly you want, so here are some options:
To get another
bytes
object: Just use thebytes
constructor.>>> bytes(swapped_nibbles) b'\x19CP\x11\x11Y\x86_'
To get an integer: Use the
int.from_bytes
constructor with big-endian byte order.>>> int.from_bytes(swapped_nibbles, byteorder='big') 1820386708623558239 # == 0x194350111159865F
To get a hex string: Use
hex
on the above integer, or build it from the individual bytes:>>> ''.join(f'{b:02X}' for b in swapped_nibbles) '194350111159865F'
It's not clear to me what exactly the rules are for excluding the last F
from the result, so you would have to add this logic yourself somehow.