1

そのため、tar 内の多数のファイルを反復処理し、そのデータを定義済みの ctype 構造にロードしようとしています。tar ファイル以外のファイルでは問題なく動作していましたが、 tarfile のメソッドによって返されたExFileObjectextractfile(member)がそのメソッドをサポートしていないことがわかりました.readinto(b)

だから今ここに私がやっていることがあります:

import os
import tarfile
import io
from ctypes import c_uint, c_char, c_ubyte, c_ushort, BigEndianStructure

class MyStructure(BigEndianStructure):
    _pack_ = True
    _fields_ = [
                ("id", c_uint), # 4 bytes
                ("namefield", c_char * 32), # 32 bytes
                ("timestamp", c_ubyte * 4), # 4 bytes
                ("payload_length", c_ushort), # 2 bytes
                ]  


def process_tar(tar_files):
    """
    untar and return file objects to be parsed
    """
    for filepath in tar_files:
        f = os.path.abspath(filepath)
        with tarfile.open(f, 'r:*') as tar_f:
            #tar_f.fileobject = io.BufferedReader
            for tarinfo_member in tar_f.getmembers():
                if tarinfo_member.isfile():
                    yield tar_f.extractfile(tarinfo_member)

f = "somefiles.tar.gz"                
for tar_member_fileobj in process_tar([f]):
    mystruct = MyStructure()
    tar_member_fileobj.readinto(mystruct)

そしてこれを得る:

---------------------------------------------------------------------------  AttributeError                            Traceback (most recent call last) <ipython-input-4-257ee4b46c31> in <module>()
     29 for tar_member_fileobj in process_tar([f]):
     30     mystruct = MyStructure()
---> 31     tar_member_fileobj.readinto(mystruct)

AttributeError: 'ExFileObject' object has no attribute 'readinto'

このメソッドを ExFileObject に追加する方法はありますか? または、定義済みの ctypes 構造にデータを簡単にロードする別の方法はありますか? tarfileオブジェクトでは、fileobject返された tarinfo ファイルに使用するように設定できるように見えますが、io.BufferedReader でスワップするだけでは機能しないようです。

(ExFileObjectをStringIOに読み込もうとしましたが、readinto()適切に実装されていないようです...extractall()メモリ内のファイルスペースにアクセスして、ファイルを標準ファイルオブジェクトとして再度開くことができると考えていますが、追加の構成が必要になるため、それを避けたい)

4

1 に答える 1

1

ExFileObject利益を生む方法ではありませんが、次を使用してファイルからヘッダーを読み取り、データを構造体にコピーするreadintoことでそれを行うことができます。readmemmove

memmove(byref(mystruct),
        tar_member_fileobj.read(sizeof(mystruct)),
        sizeof(mystruct)
)

例えば:

import os
import tarfile
import io
from ctypes import *

class MyStructure(BigEndianStructure):
    _pack_ = True
    _fields_ = [
                ("id", c_uint), # 4 bytes
                ("namefield", c_char * 32), # 32 bytes
                ("timestamp", c_ubyte * 4), # 4 bytes
                ("payload_length", c_ushort), # 2 bytes
                ]  


def process_tar(tar_files):
    """
    untar and return file objects to be parsed
    """
    for filepath in tar_files:
        f = os.path.abspath(filepath)
        with tarfile.open(f, 'r:*') as tar_f:
            #tar_f.fileobject = io.BufferedReader
            for tarinfo_member in tar_f.getmembers():
                if tarinfo_member.isfile():
                    yield tar_f.extractfile(tarinfo_member)



# test tar.gz file
open('somefiles.tar.gz', 'wb').write(
'\x1f\x8b\x08\x08\xad\x5c\x34\x52\x02\x00\x66\x6f\x6f\x2e\x74\
\x61\x72\x00\xed\xca\x49\x0a\x83\x40\x14\x04\xd0\x7f\x85\xdc\
\xa0\x43\x92\x6d\xf8\xdd\xa6\xed\x6d\xe6\xc9\x79\x1e\x76\x82\
\x0a\x82\x4b\xef\x8f\xf6\x42\xf0\x02\x6e\xe4\xbf\x4d\x41\x55\
\xb5\x5d\xdf\x9c\xeb\x6a\xa8\x60\x3d\x1c\x51\x29\xc5\x80\x69\
\xb8\xc8\x99\x14\x8c\x0b\xc1\x25\x4a\x53\x5c\x4c\x5d\x28\x9c\
\xfe\x08\x64\x6d\xbb\xc9\xed\xfe\x78\xbe\xde\x9f\xef\xef\x6f\
\xd9\x8e\xeb\xf9\x41\x18\xc5\x49\x9a\xe5\x45\xb9\xbf\x1e\x8e\
\x27\xd0\xbb\x61\x00\x21\x84\x90\x0d\x19\x01\xd4\xe8\x88\xcf\
\x00\x08\x00\x00'
)

f = "somefiles.tar.gz"                
for tar_member_fileobj in process_tar([f]):
    mystruct = MyStructure()

    memmove(byref(mystruct),
            tar_member_fileobj.read(sizeof(mystruct)),
            sizeof(mystruct)
    )

    print hex(mystruct.id)
    print mystruct.namefield
    print ''.join(map(chr, mystruct.timestamp))
    print hex(mystruct.payload_length)

文字列\x1f\x8b\x08\x08\xad ...は tar.gz ファイルで、以下が含まれます。

\x11\x11\x11\x11ABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%\x00ABCD33

そのデータをコピーすると、次のように出力されmystructます。

0x11111111L
ABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%
ABCD
0x3333
于 2013-09-14T13:28:04.617 に答える