将.readinto(b)方法添加到tarfile的ExFileObject中?

时间:2013-09-13 16:25:30

标签: python ctypes tarfile

所以我试图在tar中迭代一些文件,然后将这些数据加载到某些ctype structures's I've defined中。哪个适用于非tar文件,但后来我发现tarfile的extractfile(member)方法返回的ExFileObject不支持.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()到内存中的文件空间并重新启动 - 打开文件作为标准文件对象,但我想避免这种情况,因为我需要额外的配置)

1 个答案:

答案 0 :(得分:1)

ExFileObject没有获得readinto方法,但你仍然可以通过使用read从文件中读取标题并使用{{1}将数据复制到结构中来实现}:

memmove

例如:

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) 是tar.gz文件,包含:

\x1f\x8b\x08\x08\xad ...

将这些数据复制到\x11\x11\x11\x11ABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%\x00ABCD33 后,应该打印:

mystruct