【问题标题】:Pack char to bytes in python using struct使用struct在python中将char打包为字节
【发布时间】:2018-06-19 01:07:48
【问题描述】:

我正在尝试使用 struct 包使用 python 将 char 打包为字节,但使用此代码打包 char 时我的代码不会返回 4 个字节:

def charToHex(s):
#check if string is unicode
if isinstance(s, str):
    print(struct.pack('<c', 'a'.encode(encoding='utf-8')))
    return '{:02x}'.format(struct.unpack('<I', struct.pack('<c', s.encode('utf-8')))[0])

#check if input is already a byte
elif isinstance(s, bytes):
    return '{:02x}'.format(struct.unpack('<I', struct.pack('<c', s))[0])

else:
    raise Exception()

谁能向我解释为什么这不起作用?我只是想将 unicode char 转换为 4 个字节并解压缩它,但它甚至不会正确打包。

【问题讨论】:

  • c format 是 C 意义上的单个字节的 char,而不是 Python 意义上的 Unicode 代码点。由于 Unicode 字符的 UTF-8 编码介于 1 到 4 个字节之间,因此您不能将 pack 用作 c。您必须做一些愚蠢的事情,例如将其填充到 4 个字节并将其打包为 4c(此时使用 UTF-32 而不是 UTF-8 要简单得多)。

标签: python struct unicode byte


【解决方案1】:

c format 是 C 意义上的单字节 char,而不是 Python 意义上的 Unicode 代码点。

同时,UTF-8 的全部意义在于它是可变宽度的。一个字符可以编码为 1 到 4 个字节。所以你不能把它打包成c。您可以将其填充为 4 个字节,然后将其打包成 4cI 或其他东西,但这样做很愚蠢。

如果您想为每个字符精确使用 4 个字节,则使用 UTF-32 会简单得多。或者,由于单个字符的 UTF-32 编码只是作为 4 字节 int 的 Unicode 代码点,这与 ord 返回的内容完全相同,您可以跳过 encode 步骤。

对于单字符 bytes确实 打包为 c 是有意义的,但是将其解压缩为 i 是没有意义的。

事实上,你甚至不清楚你在这里使用struct 是为了什么。如果您想要做的只是 pack 一个数字和 unpack 同一个数字,请按原样使用数字。

同时,02x 作为 4 字节整数的格式没有多大意义,因为 4 字节整数需要 8 个十六进制数字,而不是 2 个。

所以,你可能想要的是这样的:

def charToHex(s):
    #check if string is unicode
    if isinstance(s, str):
        return format(ord(s), '08x')
    #check if input is already a byte
    elif isinstance(s, bytes):
        return format(ord(s), '02x')

【讨论】:

  • 非常感谢!我做 02x 是因为我希望输出是两个十六进制数字而不是整个数字,因为我希望它只返回两个十六进制数字。
  • @Silver 那么对于像ł 这样的代码点在十六进制中为 3 位或更多位的非 ASCII 字符,您希望返回哪两个十六进制数字?
  • Aaah 我明白你的意思,但该程序不会将非 ASCII 字符作为输入,我必须遵守该程序的要求。
  • @Silver 在这种情况下,如果给定str,您可以s = s.encode(‘ascii'),然后只处理bytes 情况。 (如果有人确实以某种方式向您传递了一个非 ASCII 字符,您会从编码中得到一个异常。)但是您可以按照您的说法使用 02x。在这种情况下,如果你以某种方式得到非 ASCII 字符,你最终会返回 3 或 4 或 7 位数字而不是 2,并且可能会搞砸你的输出而不是引发异常。这对于生产网络服务器来说不是很好,但对于甚至没有提到非 ASCII 字符的家庭作业,是的,我敢打赌它很好。
猜你喜欢
  • 2023-01-07
  • 1970-01-01
  • 2017-05-30
  • 2021-11-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多