【问题标题】:Get Whole String From a Struct Pack in Python?从 Python 中的结构包中获取整个字符串?
【发布时间】:2015-04-22 14:19:59
【问题描述】:

我要做的是从 Python 结构中获取全长字符串。 这是我的结构:struct.pack('6s','Hello!') 这是'Hello!'。 但是,当我在做struct.unpack('s','Hello!') 时,我得到一个错误:error: unpack requires a string argument of length 1。一种答案是获取输入的长度并将其放在“s”之前,但是在更复杂的情况下,您会获得包含多个字符串的结构。所以我想知道的是如何从一个有很多部分的结构中获取一个字符串。例如,一个结构体包含int, string, unsigned short, string

Tl;Dr:如何在不知道字符串长度的情况下从具有多个整数的结构中获取完整字符串?

对真实结构的了解更多:

Int, string (known size-是服务器的IP地址(我是服务器)), Short, short, short, string (unknown size-is Username).

【问题讨论】:

  • 你需要知道进入结构的字符串的大小。
  • 你知道你的字符串是空终止还是类似 - 否则,你需要知道长度...
  • 没有空终止或类似的东西

标签: python string struct


【解决方案1】:

使用

string = 'Hello!'
struct_fmt = "{}s".format(len(string))
struct.pack(struct_fmt, string)
struct.unpack(struct_fmt, string)

如果要正确解包,您必须了解要打包的数据。要解压 int, string, unsigned short, string 多种数据类型,您的 struct_fmt 将如下所示:

struct_fmt = "I %ds H %ds" % (len(string1), len(string2))

stuct 只支持定长结构。对于变长字符串,可以动态构造格式字符串,先转换成bytes再传递给pack()/unpack()

string1 = bytes(string1, 'utf-8')
struct.pack("I%ds H %ds" % (len(string1),), len(string1), string1)

所以对于你的例子:

string1 = 'Hello!'
string2 = 'Goodbye!'
s = bytes(string1, 'utf-8')
s2 = bytes(string2, 'utf-8')
struct.pack("I I%ds H I%ds" % ((len(s),), len(s), s), (len(s2),), len(s2), s2)

integershort 被省略的地方

【讨论】:

  • 问题是我不知道字符串的长度是多少:它将是从游戏发送的原始数据,我试图从本质上解释这个顺序:Int, string, unsinged short , 字符串, 长, 字符串
【解决方案2】:

您可以使用帕斯卡字符串来完成这项工作。 Pascal 字符串以长度为前缀,但标准 struct 包不支持变长 pascal 字符串。

这是我编写的一些包装函数,它们似乎有用。

这是解包助手:

def unpack_from(fmt, data, offset = 0):
    (byte_order, fmt, args) = (fmt[0], fmt[1:], ()) if fmt and fmt[0] in ('@', '=', '<', '>', '!') else ('@', fmt, ())
    fmt = filter(None, re.sub("p", "\tp\t",  fmt).split('\t'))
    for sub_fmt in fmt:
        if sub_fmt == 'p':
            (str_len,) = struct.unpack_from('B', data, offset)
            sub_fmt = str(str_len + 1) + 'p'
            sub_size = str_len + 1
        else:
            sub_fmt = byte_order + sub_fmt
            sub_size = struct.calcsize(sub_fmt)
        args += struct.unpack_from(sub_fmt, data, offset)
        offset += sub_size
    return args

这是打包助手:

def pack(fmt, *args):
    (byte_order, fmt, data) = (fmt[0], fmt[1:], '') if fmt and fmt[0] in ('@', '=', '<', '>', '!') else ('@', fmt, '')
    fmt = filter(None, re.sub("p", "\tp\t",  fmt).split('\t'))
    for sub_fmt in fmt:
        if sub_fmt == 'p':
            (sub_args, args) = ((args[0],), args[1:]) if len(args) > 1 else ((args[0],), [])
            sub_fmt = str(len(sub_args[0]) + 1) + 'p'
        else:
            (sub_args, args) = (args[:len(sub_fmt)], args[len(sub_fmt):])
            sub_fmt = byte_order + sub_fmt
        data += struct.pack(sub_fmt, *sub_args)
    return data

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-11-03
    • 2022-09-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-11
    • 1970-01-01
    • 2012-07-05
    相关资源
    最近更新 更多