2

これはひどく間違っていると確信しており、いくつか問題があります。WIN32_FIND_DATAW構造体の配列を次々にディスクに書き出しました。Pythonスクリプトでそれらを使用して解析したいと思います。

私が現在使用しているコードは次のとおりです。

>>> fp = open('findData', 'r').read()
>>> data = ctypes.cast(fp, ctypes.POINTER(wintypes.WIN32_FIND_DATAW))
>>> print str(data[0].cFileName)

最初の問題は、3行目が私が期待するような素敵な文字列を印刷しないことです。印刷する代わりに印刷$Recycle.BinしますUnicodeEncodeError: 'ascii' codec can't encode characters in position 0-5: ordinal not in range(128)

これは、そこに保存されているデータを印刷した結果です。

>>> data[0].cFileName
u'\U00520024\U00630065\U00630079\U0065006c\U0042002e\U006e0069'

これは比較的合理的に見えます。 $はASCII0x24、RはASCII0x52などです。

では、なぜ文字列のように印刷できないのでしょうか。

私の2番目の質問はそれをすることです:

>>> 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  |................|

必要に応じて、さらにデータを投稿できます。

4

2 に答える 2

2

コメントですでに述べたように、これはWindowsとLinuxの違いによるものです。モジュールはctypesローカル環境に適合しようとするため、不一致が発生します。最善の解決策は、モジュールを使用structしてプラットフォームに依存しない方法でモジュールを処理することです。次のコードは、単一のレコードに対してこれを実行する方法を示しています。

# Setup test data based on incomplete sample
bytes = "\x16\x00\x00\x00\xdc\x5a\x9f\xd2\x31\x04\xca\x01\xba\x81\x89\x1a\x81\xe2\xcd\x01\xba\x81\x89\x1a\x81\xe2\xcd\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x24\x00\x52\x00\x65\x00\x63\x00\x79\x00\x63\x00\x6c\x00\x65\x00\x2e\x00\x42\x00\x69\x00\x6e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
bytes = bytes + "\x00"*(592-len(bytes))

import struct
import codecs

# typedef struct _WIN32_FIND_DATA {
#   DWORD    dwFileAttributes;
#   FILETIME ftCreationTime;
#   FILETIME ftLastAccessTime;
#   FILETIME ftLastWriteTime;
#   DWORD    nFileSizeHigh;
#   DWORD    nFileSizeLow;
#   DWORD    dwReserved0;
#   DWORD    dwReserved1;
#   TCHAR    cFileName[MAX_PATH];
#   TCHAR    cAlternateFileName[14];


fmt = "<L3Q4L520s28s"

attrs, creation, access, write, sizeHigh, sizeLow, reserved0, reserved1, name, alternateName = struct.unpack(fmt, bytes)
name = codecs.utf_16_le_decode(name)[0].strip('\x00')
alternateName = codecs.utf_16_le_decode(alternateName)[0].strip('\x00')
print name

注:これは、MAX_PATHのサイズが260であることを前提としています(これは正しいはずですが、わかりません)。

ファイルからすべての値を読み取るには、一度に592バイトのブロックを読み取り、上記のようにデコードする必要があります。

于 2013-03-24T09:44:40.837 に答える
0

バイナリファイル形式を解析しているためstruct、標準ライブラリhttp://docs.python.org/2/library/struct.htmlのモジュールを使用する必要があります。このctypesモジュールは、共有ライブラリ(DLL)とバイナリAPIをPythonアプリに統合するために使用されます。あなたがやろうとしていることが不可能だと言っているわけではありませんがctypes、バイナリファイルからC構造体を解析するよりも、使用はより複雑です。

Cには、PWIN32_FIND_DATAWポインターのようなものはないことを覚えておいてください。これは、32ビットポインタ、64ビットポインタなどの生のCデータ型の1つに解決される単なるtypedefです。ファイル内のデータは生のベースCデータ型を表します。

コメントへの回答で...ショートカットを探すのは避けてください。ファイルに書き込まれているビットとそれらがどのように編成されているかを深く理解する必要があります。そのためには、いくつかの16進ダンプを実行し、実際のデータ表現を確認する必要があります。MSによるとhttp://msdn.microsoft.com/en-ca/library/windows/desktop/aa365740(v=vs.85).aspxこれは実際の複雑な構造ではありません。wintypesの構造が機能しない場合は、バグを見つけた可能性があります。また、ディスク上の構造がRAM内の構造と同一でない可能性もあります。多くの場合、RAM内のデータ構造には、16バイトまたは64バイトの境界での位置合わせを維持するためのパディングが含まれます。しかし、プログラマーは構造体をそのままダンプするのではなく、構造体を分解して、パディングを除いたファイルに出力することが知られています。ctypes / wintypesはDLLへのバイナリAPI呼び出しを行うことを目的としているため、そのバイアスはデータレイアウトにパディングを含めることです。ただし、ファイルにこれが含まれていない可能性があります。

于 2013-03-24T09:02:48.617 に答える