7

ファイルのコレクションまたは単一の複合ファイルにデータを保存しています。複合ファイルは、すべての個別のファイルを連結し、すべての前に、構成要素のオフセットとサイズを示すヘッダーを付けることによって形成されます。複合ファイルのビューを表示するファイルのようなオブジェクトが欲しいのですが、ビューはメンバーファイルの1つだけを表しています。(こうすることで、実際のファイルオブジェクトまたは「ビュー」オブジェクトのいずれかを受け入れるデータを読み取るための関数を使用できます。特定のデータセットがどのように格納されるかを気にする必要はありません。)これはどのライブラリで実行されますか?

このmmapクラスは、ファイル、長さ、およびオフセットから構築されているため、有望に見えました。これはまさに私が持っているものですが、オフセットは、基になるファイルシステムの割り当ての粒度に合わせる必要があり、私が読んでいるファイルはそうではありません。その要件を満たします。クラスの名前MultiFile法案に適合しますが、電子メールメッセージの添付ファイルに合わせて調整されており、私のファイルにはその構造がありません。

私が最も興味を持っているファイル操作は、、、readおよびseekですtell。私が読んでいるファイルはバイナリなので、テキスト指向の関数はそれほど重要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 に答える