7

我将数据存储在文件集合或单个复合文件中。复合文件是通过连接所有单独的文件形成的,然后在所有内容之前加上一个标题,该标题给出了组成部分的偏移量和大小。我想要一个类似文件的对象,它呈现复合文件的视图,其中视图仅代表一个成员文件。(这样,我可以拥有读取数据的函数,这些函数可以接受真实的文件对象或“视图”对象,而且他们不必担心任何特定数据集的存储方式。)哪个库会为我做这件事?

这个mmap类看起来很有希望,因为它是由一个文件、一个长度和一个偏移量构成的,这正是我所拥有的,但是偏移量需要与底层文件系统的分配粒度保持一致,而我正在读取的文件不满足那个要求。该类的名称符合MultiFile要求,但它是为电子邮件中的附件量身定制的,而且我的文件没有这种结构。

我最感兴趣的文件操作是read,seektell. 我正在阅读的文件是二进制文件,因此面向文本的函数readline并不next那么重要。我可能最终也需要write,但我现在愿意放弃该功能,因为我不确定附加应该如何表现。

4

2 回答 2

4

我知道你正在寻找一个图书馆,但是当我读到这个问题时,我想我会自己写。所以这里是:

import os

class View:
    def __init__(self, f, offset, length):
        self.f = f
        self.f_offset = offset
        self.offset = 0
        self.length = length

    def seek(self, offset, whence=0):
        if whence == os.SEEK_SET:
            self.offset = offset
        elif whence == os.SEEK_CUR:
            self.offset += offset
        elif whence == os.SEEK_END:
            self.offset = self.length+offset
        else:
            # Other values of whence should raise an IOError
            return self.f.seek(offset, whence)
        return self.f.seek(self.offset+self.f_offset, os.SEEK_SET)

    def tell(self):
        return self.offset

    def read(self, size=-1):
        self.seek(self.offset)
        if size<0:
            size = self.length-self.offset
        size = max(0, min(size, self.length-self.offset))
        self.offset += size
        return self.f.read(size)

if __name__ == "__main__":
    f = open('test.txt', 'r')

    views = []
    offsets = [i*11 for i in range(10)]

    for o in offsets:
        f.seek(o+1)
        length = int(f.read(1))
        views.append(View(f, o+2, length))

    f.seek(0)

    completes = {}
    for v in views:
        completes[v.f_offset] = v.read()
        v.seek(0)

    import collections
    strs = collections.defaultdict(str)
    for i in range(3):
        for v in views:
            strs[v.f_offset] += v.read(3)
    strs = dict(strs) # We want it to raise KeyErrors after that.

    for offset, s in completes.iteritems():
        print offset, strs[offset], completes[offset]
        assert strs[offset] == completes[offset], "Something went wrong!"

我编写了另一个脚本来生成“test.txt”文件:

import string, random

f = open('test.txt', 'w')

for i in range(10):
    rand_list = list(string.ascii_letters)
    random.shuffle(rand_list)
    rand_str = "".join(rand_list[:9])
    f.write(".%d%s" % (len(rand_str), rand_str))

它对我有用。我测试的文件不是像你这样的二进制文件,它们也没有你的那么大,但我希望这可能有用。如果没有,那么谢谢你,这是一个很好的挑战:D

另外,我想知道,如果这些实际上是多个文件,为什么不使用某种存档文件格式,并使用它们的库来读取它们呢?

希望能帮助到你。

于 2012-07-03T15:46:16.123 回答
3

根据您需要的复杂程度,这样的事情应该可以工作——我已经省略了一些细节,因为我不知道您需要多接近地模拟文件对象(例如,您会使用obj.read(), 或你会一直使用obj.read(nbytes)):

class FileView(object):
     def __init__(self,file,offset,length):
         self._file=file
         self._offset=offset
         self._length=length

     def seek(self,pos):
         #May need to get a little fancier here to support the second argument to seek.
         return self._file.seek(self._offset+pos)

     def tell(self):
         return self._file.tell()-self._offset

     def read(self,*args):
         #May need to get a little more complicated here to make sure that the number of
         #bytes read is smaller than the number of bytes available for this file
         return self._file.read(*args)
于 2012-07-03T15:29:46.943 回答