【问题标题】:How to byteswap 32bit integers inside a string in python?如何在python中的字符串中对32位整数进行字节交换?
【发布时间】:2013-06-04 05:22:56
【问题描述】:

我有一个超过 256 位的大字符串,我需要将它的字节交换为 32 位。但字符串是十六进制的。当我查看 numpy 和 array 模块时,我找不到关于如何进行覆盖的正确语法。有人可以帮帮我吗?

一个例子:(认为数据要长得多。我可以使用pack,但是我必须先将小端转换为十进制,然后再转换为大端,这似乎很浪费):

Input:12345678abcdeafa
Output:78563412faeacdab

【问题讨论】:

  • 可能有包,但你必须不那么模糊。
  • 每个十六进制数字是 4 位,我想您可以将字符串切成半字大小的块并交换奇数/偶数块。
  • 这看起来不像是字节序交换,除非你有 4 位字节。
  • ...但是你所拥有的不会交换字节,除非你有 4 位字节。假设 8 位字节,交换 12345678 得到 78563412,而不是 87654321
  • 输入/输出是十六进制数字的字符串还是十六进制文字或其他什么??

标签: python


【解决方案1】:

将字符串转换为字节,将 big-endian 32 位解包并打包 little-endian 32 位(反之亦然)并转换回字符串:

#!python3
import binascii
import struct

Input = b'12345678abcdeafa'
Output = b'78563412faeacdab'

def convert(s):
    s = binascii.unhexlify(s)
    a,b = struct.unpack('>LL',s)
    s = struct.pack('<LL',a,b)
    return binascii.hexlify(s)

print(convert(Input),Output)

输出:

b'78563412faeacdab' b'78563412faeacdab'

泛化为长度为 4 的倍数的任何字符串:

import binascii
import struct

Input = b'12345678abcdeafa'
Output = b'78563412faeacdab'

def convert(s):
    if len(s) % 4 != 0:
        raise ValueError('string length not multiple of 4')
    s = binascii.unhexlify(s)
    f = '{}L'.format(len(s)//4)
    dw = struct.unpack('>'+f,s)
    s = struct.pack('<'+f,*dw)
    return binascii.hexlify(s)

print(convert(Input),Output)

【讨论】:

  • 我看到除了 OP 以外的其他人更改了问题,但我还是会留下答案。
  • 很可能原来的Output 是错误的,而这个答案给出了正确的答案。
【解决方案2】:

如果它们真的是字符串,只对它们进行字符串操作?

>>> input = "12345678abcdeafa"
>>> input[7::-1]+input[:7:-1]
'87654321afaedcba'

【讨论】:

  • 为什么会被接受?它与 OP 的示例输出不匹配。
  • @MarkTolonen 这个答案符合 OP 的要求。问题中的示例输出已由 icktoofay 更改。 (OP实际需要的可能还是78563412faeacdab)
  • @Janne,OP 应该把它改回来,尽管我认为你对 OP 可能需要的东西是正确的。通常不需要 32 位 nybble 交换数据。
  • 让我感到困惑的是,为什么@icktoofay 在 OP 确认他的输出是什么之后改变了问题......
  • @Kimvais: icktoofay 有 40k+ 声望,user1667307 不知道。我的赌注是 icktoofay。
【解决方案3】:

我的看法:

  1. 将字符串分成 N 位块
  2. 反转每个块
  3. 连接所有内容

例子:

>>> source = '12345678abcdeafa87654321afaedcba'
>>> # small helper to slice the input in 8 digit chunks
>>> chunks = lambda iterable, sz: [iterable[i:i+sz] 
                                   for i in range(0, len(iterable), sz)]
>>> swap = lambda source, sz: ''.join([chunk[::-1] 
                                       for chunk in chunks(source, sz)])

原始问题中询问的输出:

>>> swap(source, 8)
'87654321afaedcba12345678abcdeafa'

很容易适应,以便在icktoofay编辑后匹配所需的输出:

>>> swap(swap(source, 8), 2)
'78563412faeacdab21436587badcaeaf'

一个正确的实现可能应该检查len(source) % 8 == 0

【讨论】:

    猜你喜欢
    • 2015-02-14
    • 2019-03-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多