2012-07-03 10 views
7

Mam dane przechowywane w zbiorze plików lub w pojedynczym złożonym pliku. Plik złożony jest tworzony przez połączenie wszystkich oddzielnych plików, a następnie poprzedzający wszystko nagłówkiem, który podaje przesunięcia i rozmiary części składowych. Chciałbym mieć obiekt plikopodobny, który przedstawia plik złożony w widoku , gdzie widok reprezentuje tylko jeden z plików składowych. (W ten sposób mogę mieć funkcje do odczytu danych, które akceptują rzeczywisty obiekt pliku lub obiekt "widok", i nie muszą się martwić o to, jak dany konkretny zestaw danych jest przechowywany.) Jaka biblioteka zrobi to za mnie?Jak traktować sekcję pliku tak, jakby był samym plikiem?

Klasa mmap wyglądała obiecująco, ponieważ została zbudowana z pliku, długości i przesunięcia, co jest dokładnie tym, co mam, ale przesunięcie musi zostać wyrównane z granularnością alokacji bazowego systemu plików, a pliki I ' odczyt m nie spełnia tego wymogu. Nazwa nazwa z klasy MultiFile pasuje do rachunku, ale jest dostosowana do załączników w wiadomościach e-mail, a moje pliki nie mają tej struktury.

Operacje na plikach, którymi jestem najbardziej zainteresowany, to: read, seek i tell. Pliki, które czytam, są binarne, więc funkcje zorientowane na tekst, takie jak readline i , nie są tak ważne. Mogę ewentualnie potrzebować również write, ale jestem gotów zrezygnować z tej funkcji, ponieważ nie jestem pewien, jak powinno się zachować dołączanie.

+1

Czy można po prostu owinąć obiekt pliku w klasie wygody, która ma 'read',' seek' i 'tell' metody, które obliczają rzeczywistą pozycję pliku z pseudo-pozycji? – mgilson

+0

Ponadto, jak duże są pliki? Czy są wystarczająco małe, aby zmieścić się wygodnie w pamięci? Jeśli tak jest, możesz być w stanie porwać je za pomocą 'StringIO' – mgilson

+0

_" [..], ale offset musi być wyrównany do granularności alokacji bazowego systemu plików, a pliki które czytam nie spełniają ten wymóg. "_ ... czy możesz to wyjaśnić? –

Odpowiedz

4

wiem, że szukali biblioteki, ale tak szybko, jak czytam to pytanie, pomyślałem, że napisać moje własne. Więc to jest tutaj:

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!" 

i napisałem inny skrypt do generowania "test.txt" file:

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)) 

pracował dla mnie. Pliki, które testowałem, nie są plikami binarnymi podobnymi do twoich, a nie są tak duże jak twoje, ale może się to przydać, mam nadzieję. Jeśli nie, to dziękuję, to było dobre wyzwanie: D

Zastanawiam się również, czy to w rzeczywistości wiele plików, dlaczego nie użyć jakiegoś formatu pliku archiwum i użyć ich bibliotek, aby je przeczytać?

Mam nadzieję, że to pomaga.

+0

Dzięki. To było pomocne. Byłoby miło użyć lepiej zdefiniowanego formatu pliku złożonego, ale nasz produkt produkuje takie pliki od prawie dziesięciu lat, więc jest już za późno na zmianę. Muszę napisać kod, aby poradzić sobie z tym, czym są pliki *, a nie tym, jak bym sobie tego życzył *. –

3

W zależności od tego, jak skomplikowane jest to potrzebne, coś takiego powinno zadziałać - odrzuciłem niektóre szczegóły, ponieważ nie wiem, jak bardzo należy emulować obiekt pliku (np. kiedykolwiek użyć obj.read(), czy zawsze będziesz używać 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) 
Powiązane problemy