我肯定这是大错特错了,我有几个问题。我已经将一个WIN32_FIND_DATAW
结构的数组一个接一个地写到磁盘上,我想在Python脚本中使用并解析它们。在
我当前使用的代码是:
>>> fp = open('findData', 'r').read()
>>> data = ctypes.cast(fp, ctypes.POINTER(wintypes.WIN32_FIND_DATAW))
>>> print str(data[0].cFileName)
第一个问题是第三行没有像我预期的那样打印出一个很好的字符串。它不是打印$Recycle.Bin
,而是打印UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-5: ordinal not in range(128)
这是打印存储在那里的数据的结果:
^{pr2}$这看起来相对合理。$
是ASCII 0x24,R
是ASCII 0x52,依此类推。在
为什么我不能像字符串一样打印它?
我的第二个问题是:
>>> data[1].cFileName
给了我荒谬的数据。我很确定我没有正确使用ctypes.cast
。我应该怎么做才能访问这些?为了澄清这一点,在C语言中,我只需将一个PWIN32_FIND_DATAW
指针指向缓冲区的开头,并使用类似的代码访问数组中的各个结构,我正尝试在Python中执行相同的操作。在
更新
正在做:
>>> data[0].cFileName.encode('windows-1252')
产生此错误:
UnicodeEncodeError: 'charmap' codec can't encode characters in position 0-5: character maps to <undefined>
更新
第一个条目的开头(data[0]
到cFileName的第一部分)如下所示:
user@ubuntu:~/data$ hexdump -C findData | head -n 6
00000000 16 00 00 00 dc 5a 9f d2 31 04 ca 01 ba 81 89 1a |.....Z..1.......|
00000010 81 e2 cd 01 ba 81 89 1a 81 e2 cd 01 00 00 00 00 |................|
00000020 00 00 00 00 00 00 00 00 00 00 00 00 24 00 52 00 |............$.R.|
00000030 65 00 63 00 79 00 63 00 6c 00 65 00 2e 00 42 00 |e.c.y.c.l.e...B.|
00000040 69 00 6e 00 00 00 00 00 00 00 00 00 00 00 00 00 |i.n.............|
00000050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
如果需要,我可以发布更多的数据。在
正如评论中已经提到的,这是由于windows和linux之间的差异造成的。
ctypes
模块试图适应本地环境,因此不匹配。最好的解决方案是使用struct
模块以独立于平台的方式处理它。下面的代码演示如何对单个记录执行此操作。在注意:这假设MAX_PATH的大小是260(这应该是真的,但是您永远不知道)。在
要从文件中读取所有值,您需要一次读取592个字节的块,然后按上面所述进行解码。在
您应该使用标准库http://docs.python.org/2/library/struct.html中的
struct
模块,因为您正在解析二进制文件格式。ctypes
模块用于将共享库(dll)与二进制API集成到Python应用程序中。我并不是说您要做的是不可能的,但是使用ctypes
比简单地从二进制文件解析C结构要复杂得多。在请记住,在C中没有PWIN32_FIND_DATAW指针。这只是一个typedef,它将解析为原始C数据类型之一,如32位指针、64位指针等。文件中的数据表示原始的基本C数据类型。在
作为对评论的回应。。。避免寻找捷径。您确实需要深入了解写入文件的位以及它们是如何组织的。为此,您可能需要执行一些hexdump并检查实际的数据表示。根据MShttp://msdn.microsoft.com/en-ca/library/windows/desktop/aa365740(v=vs.85).aspx,这不是一个真正的复杂结构。如果wintypes中的结构不适合您,则可能是您发现了一个bug。磁盘上的结构也可能与内存中的结构不同。通常,ram中的数据结构包括填充以保持16或64字节边界上的对齐。但众所周知,程序员不会将结构按原样转储,而是将其分离并输出到一个减去填充的文件中。因为ctypes/wintypes是用来对DLL进行二进制api调用的,所以它的偏向是在数据布局中包含填充。但文件可能不包括这个。在
相关问题 更多 >
编程相关推荐