解码、小端、未压缩和浮点数组

6 投票
3 回答
11660 浏览
提问于 2025-04-17 02:28

我有一些经过Base64编码的数据,这些数据来自一个实验。现在我想一步一步地做以下事情:

  • 从Base64编码中提取字节(解码)
  • 将字节转换为小端格式
  • 从(zlib)解压缩字节
  • 将字节数组转换为浮点数组

举个例子:

Dn3LQ3np4kOyxQJE20kDRBRuFkScZB5ENxEzRFa+O0THMz9EOQRCRFC1QkRYeUNEwXJJROfbSUScvE5EVDtVRK5PV0TLUWNE481lRHX7ZkSBBWpE9FVyRIFdeESkoHhEnid8RI1nfUSy4YBE/C2CRGKQg0RcR4RE54uEROUAhUTBWodErKyMRNsVkkRvUpJEukWURO58lkSqRZ1E2VauRPBTwEQf9cVE9BnKRA==

我到目前为止尝试过的内容:

import os
import base64
import struct

s = 'Dn3LQ3np4kOyxQJE20kDRBRuFkScZB5ENxEzRFa+O0THMz9EOQRCRFC1QkRYeUNEwXJJROfbSUScvE5EVDtVRK5PV0TLUWNE481lRHX7ZkSBBWpE9FVyRIFdeESkoHhEnid8RI1nfUSy4YBE/C2CRGKQg0RcR4RE54uEROUAhUTBWodErKyMRNsVkkRvUpJEukWURO58lkSqRZ1E2VauRPBTwEQf9cVE9BnKRA=='
decode=base64.decodestring(s)

tmp_size=len(decode)/4

现在我想从这里开始将这些字节转换为小端格式。

我想在Python中进行下一步操作。

我正在努力自己搞明白,但这花了我太多时间。

谢谢!

3 个回答

0

看起来你接下来的步骤是使用 struct。可以这样做:

struct.unpack("<f", decode[0:4])

这个例子会把 decode 的前四个字节转换成一个浮点数。想了解更多关于格式字符串等的信息,可以查看struct 的文档

1

将字节转换为小端格式

字节顺序只适用于大于1个字节的数据类型。所以你不能仅仅把一串字节转换成小端格式。你需要了解你字节列表中的内容。

一个32位的整数占4个字节;如果你有16个字节的数据,你可以把它“拆分”成4个32位的整数。

如果数据只是ASCII文本,那么字节顺序就不重要了,这就是为什么你可以在大端和小端的机器上读取完全相同的ASCII文本文件。

下面是一个演示如何使用struct.pack和struct.unpack的例子:

#!/usr/bin/env python2.7
import struct
# 32-bit unsigned integer
# base 10       2,864,434,397
# base 16       0xAABBCCDD
u32 = 0xAABBCCDD
print 'u32 =', u32, '(0x%x)' % u32
# big endian    0xAA 0xBB 0xCC 0xDD
u32be = struct.pack('>I', u32)
bx = [byte for byte in struct.unpack('4B', u32be)]
print 'big endian packed', ['0x%02x' % x for x in bx]
assert bx == [0xaa, 0xbb, 0xcc, 0xdd]
# little endian 0xDD 0xCC 0xBB 0xAA
u32le = struct.pack('<I', u32)
lx = [byte for byte in struct.unpack('4B', u32le)]
print 'little endian packed', ['0x%02x' % x for x in lx]
assert lx == [0xdd, 0xcc, 0xbb, 0xaa]
# 64-bit unsigned integer
# base 10       12,302,652,060,662,200,000
# base 16       0xAABBCCDDEEFF0011
u64 = 0xAABBCCDDEEFF0011L
print 'u64 =', u64, '(0x%x)' % u64
# big endian    0xAA 0xBB 0xCC 0xDD 0xEE 0xFF 0x00 0x11
u64be = struct.pack('>Q', u64)
bx = [byte for byte in struct.unpack('8B', u64be)]
print 'big endian packed', ['0x%02x' % x for x in bx]
assert bx == [0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x00, 0x11]
# little endian 0x11 0x00 0xFF 0xEE 0xDD 0xCC 0xBB 0xAA
u64le = struct.pack('<Q', u64)
lx = [byte for byte in struct.unpack('8B', u64le)]
print 'little endian packed', ['0x%02x' % x for x in lx]
assert lx == [0x11, 0x00, 0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa]

想了解更多信息,可以查看文档:http://docs.python.org/library/struct.html#format-strings

6

看起来你的数据其实并没有被压缩。你可以用循环的方式把数据当作浮点数读取,使用struct.unpack_from()这个方法,或者把它作为一个大结构一次性读取,使用struct.unpack()

import base64
import struct

encoded = 'Dn3LQ3np ... 9BnKRA=='

# decode the string
data = base64.standard_b64decode(encoded)

# ensure that there's enough data for 32-bit floats
assert len(data) % 4 == 0

# determine how many floats there are
count = len(data) // 4

# unpack the data as floats
result = struct.unpack('<{0}f'.format(count), # one big structure of `count` floats
                       data)                  # results returned as a tuple

如果数据是压缩过的,那就先解压缩它。

import zlib

decompressed = zlib.decompress(data)

撰写回答