如何从非 ascii 字符中获取 char 值
Posted
技术标签:
【中文标题】如何从非 ascii 字符中获取 char 值【英文标题】:How can you get char values from non ascii character 【发布时间】:2019-10-17 15:28:21 【问题描述】:你好,所以我在 python 类型中有一个字符串POINTER(wintypes.BYTE)
我在 python 中使用DATA_BLOB(
class CREATE_DATA_BLOB(Structure):
_fields_ = [('cbData', wintypes.DWORD), ('pbData', POINTER(wintypes.BYTE))]
) 我有一个加密数据的 DLL。加密数据后,数据保存在 data_blob 结构的pbData
中。问题是 pbData
(pbData[0]
) 中的值,例如其中有 -42
,另一个例子是其中一些在 0 到 255 之间 - 它们很好,但有些完全是随机数,我可以t 弄清楚如何将这些非 ASCII 数字转换为字符。在 c++ 中,我使用 writeFile 函数,我只发送 pbData
并且在 python 中一切正常,如果我试图将 pbData
写入文本文件,我会遇到此错误:
file.write(data_out.pbData)
TypeError: write() argument must be str, not LP_c_byte
我真的不知道如何解决这个问题。
【问题讨论】:
我认为wintypes.BYTE
是signed char
或char
(通常也是签名的)。你真的得到了介于 128 和 255 之间的 wintypes.BYTE
值吗?
在 Windows 中,BYTE
是 unsigned
(0-255)。 wintypes.BYTE
已签名 (128-127)。如果 wintypes.BYTE
为负数,您只需将 256 添加到它即可获得与 C++ 中相同的值(在 2 的补码机器上)。
它使用你想要的类型。在 Windows (C++) 中,BYTE
定义为 unsigned char
。不幸的是,wintypes.BYTE
没有映射到任务的正确类型(因为它由于某种原因被烧掉了)。在查看 ctypes/wintypes.py
时,我看到有一个 UCHAR
类型 - 但它已被注释掉。否则,我会尝试使用它。
@TedLyngmo 非常感谢
好吧,在你做了 +256 之后,你的值应该在 0 到 255(包括)之间。如果这还不够,您还有其他问题可以通过以二进制模式写入文件来解决(请参阅@CristiFati 的回答)。
【参考方案1】:
上市[Python 3.Docs]: ctypes - A foreign function library for Python。
有几个问题:
wintypes.BYTE
已签名 ([Python.Bugs]: wrong type for wintypes.BYTE)
file.write
适用于 Python 字符串(在您的情况下)而不是 ctypes 指针(并且它们之间没有隐式转换)
更进一步(这将在解决其他 2 个问题后出现):您的缓冲区中有“特殊”字符。这意味着您不应将 is 视为“普通字符串”,而应将其视为二进制序列(否则您可能会遇到编码/解码错误)。因此,以二进制模式(例如:file = open(file_name, "wb")
)打开您要将其内容转储到的文件。
>>> import ctypes as ct >>> from ctypes import wintypes as wt >>> >>> class CREATE_DATA_BLOB(ct.Structure): ... _fields_ = [ ... ("cbData", wt.DWORD), ... ("pbData", ct.POINTER(ct.c_ubyte)), # wt.BYTE is signed !!! ... ] ... >>> >>> buf_initial = b"AB\xD6CD\xD9EF\x9CGH" # Contains the 3 chars you mentioned >>> buf_initial b'AB\xd6CD\xd9EF\x9cGH' >>> # Populate the structure as it was done from C++ ... >>> blob = CREATE_DATA_BLOB(len(buf_initial), ct.cast(ct.create_string_buffer(buf_initial), ct.POINTER(ct.c_ubyte))) >>> blob.cbData, blob.pbData (11, <__main__.LP_c_ubyte object at 0x00000154FF6998C8>) >>> >>> buf_final = bytes(blob.pbData[:blob.cbData]) # Convert the pointer explicitly to Python bytes >>> buf_final b'AB\xd6CD\xd9EF\x9cGH' >>> buf_initial == buf_final True >>> >>> with open("q058436070_out.bin", "wb") as file: ... file.write(buf_final) ... 11
【讨论】:
当我想解密数据时,我应该将其读取为字节吗?以及文本文件的外观以及它们必须是二进制正确的常规字符呢? 您应该绝对将其读取为字节。如果您将其作为文本阅读,则应在之后将其转换为字节,您将在此处出现错误。请注意(简化的)Python 3 字符串映射到 Win 上的wchar_t*
。
写入文件的字节数(与上面几行显示的blob.cbData
相同)。
但是如何将加密后的数据打印到文本文件中呢?
“打印到文本文件”是什么意思?最后几行将加密数据写入文件。但是二进制数据和文本文件不太匹配。以上是关于如何从非 ascii 字符中获取 char 值的主要内容,如果未能解决你的问题,请参考以下文章