如何从非 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.BYTEsigned charchar(通常也是签名的)。你真的得到了介于 128 和 255 之间的 wintypes.BYTE 值吗? 在 Windows 中,BYTEunsigned (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 值的主要内容,如果未能解决你的问题,请参考以下文章

如何在JavaScript中获取字符的ASCII值[重复]

c语言编程中如何显示字符的ASCII码值?

如何从非托管 C++ 代码获取结构化列表值到 C#?

如何将 ASCII 字符的十六进制值写入文本文件?

Emacs Lisp:获取字符的 ascii 值

char[] 转换成 ascii 和十进制值 (double) java