我将数据存储在文件集合或单个复合文件中。复合文件是通过连接所有单独的文件形成的,然后在所有内容前面加上一个标题,该标题给出了组成部分的偏移量和大小。我想要一个类似文件的对象,它提供了复合文件的 view ,其中视图只代表其中一个成员文件。 (这样,我可以使用函数来读取接受真实文件对象或“视图”对象的数据,而且他们不必担心任何特定数据集的存储方式。)什么库会为我做这个? / p>
mmap
类看起来很有前途,因为它是由文件,长度和偏移量构成的,这正是我所拥有的,但是偏移量需要与底层文件系统的分配粒度一致,并且我正在阅读的文件不符合要求。 MultiFile
类的名称符合要求,但它是为电子邮件中的附件量身定制的,而我的文件没有这种结构。
我最感兴趣的文件操作是read
,seek
和tell
。我正在阅读的文件是二进制文件,因此面向文本的函数如readline
和next
并不是那么重要。我最终可能还需要write
,但我现在愿意放弃这个功能,因为我不确定附加应该如何表现。
答案 0 :(得分: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
另外,我想知道,如果这些文件实际上是多个文件,为什么不使用某种存档文件格式,并使用它们的库来读取它们?
希望它有所帮助。
答案 1 :(得分: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)