2016-06-16 1 views
1

Я новичок в python, поэтому не знаю некоторых основных вещей. У меня есть двоичный файл, который содержит массив объектов. Объекты, хранящиеся, являются традиционными структурами C. Я хотел бы воссоздать эту структуру в python и прочитать содержимое файла в списке его объектов, внести некоторые изменения в данные и сохранить их обратно. Часть, с которой у меня возникают проблемы, это чтение содержимого файла. Я прочитал некоторые подобные вопросы о чтении файла, но они не ответили на мои вопросы. Я пробовал определять класс и определять членов класса с __slot__ и считывать данные с pickle, но это не совсем сработало. Также может быть уместным, что один из элементов данных фактически представляет собой массив, содержащий объекты разной структуры. Каким будет лучший способ прочитать этот файл?python читает элемент данных класса из файла

ответ

0

Вам необходимо использовать python's struct.unpack(). Вам нужно точно знать, какие они есть, и как они упакованы на диск. pickle специфичен для формата хранения Python и не будет вам полезен, если вы не конвертируете сериализацию в какой-то конкретный python.

Я недавно ответил неопределенно подобный вопрос here, который показал, как использовать mmap() в файл, который вы можете найти более удобным, чем os.read()

я бы, вероятно, начать с создания класса, который имеет конструктор, где вы инициализировать его с некоторой комбинацией указателя файла, mmap объекта и смещения.

Затем метод __init___() будет считывать и инициализировать атрибуты self с распакованным содержимым структуры. Затем добавить методы доступа, чтобы изменить эти атрибуты, а затем метод save(), чтобы написать их все обратно, используя struct.pack с mmap() или os.write

Вот пример из Python Docs упаковки и распаковки три целых числа (2 16bit шорты с последующим 32-разрядная долго):

>>> from struct import * 
>>> pack('=hhl', 1, 2, 3) 
'\x00\x01\x00\x02\x00\x00\x00\x03' 
>>> unpack('=hhl', '\x00\x01\x00\x02\x00\x00\x00\x03') 
(1, 2, 3) 
>>> calcsize('hhl') 
8 

Похоже, ваши данные могут быть переменной длиной ... означает, что вы не можете быть в состоянии изменить данные на месте.

Вот пример Python2 с использованием как os.read(), так и mmap. I pre-created /tmp/three_numbers.dat с dd if=/dev/zero of=/tmp/three_numbers.dat count=1 bs=1k:

import mmap 
import os 
import struct 


class ThreeNumbers(object): 

    PACK = '=hhl' 
    SIZEOF = struct.calcsize(PACK) 

    def __init__(self, fd, offset): 
     self._fd = fd 
     self._offset = offset 
     self._fd.seek(offset * self.SIZEOF) 
     self._data = os.read(fd.fileno(), self.SIZEOF) 
     self.numbers = struct.unpack(self.PACK, self._data) 

    def save(self): 
     self._fd.seek(self._offset * self.SIZEOF) 
     os.write(self._fd.fileno(), struct.pack(self.PACK, *self.numbers)) 


class ThreeNumbersMMAP(object): 

    PACK = '=hhl' 
    SIZEOF = struct.calcsize(PACK) 

    def __init__(self, mmap, offset): 
     self._mmap = mmap 
     self._offset = offset 
     self._data = mmap[offset * self.SIZEOF:(offset + 1) * self.SIZEOF] 
     self.numbers = struct.unpack(self.PACK, self._data) 

    def save(self): 
     self._mmap[self._offset * self.SIZEOF:(self._offset + 1) * self.SIZEOF] = struct.pack(self.PACK, *self.numbers) 


fd = open("/tmp/three_numbers.dat", "rb+") 

obj = ThreeNumbers(fd, 0) 
print obj.numbers 
obj.numbers = (1, 2, 3) 
obj.save() 

obj = ThreeNumbers(fd, 0) 
print obj.numbers 
obj.numbers = (0, 0, 0) 
obj.save() 

mmap = mmap.mmap(fd.fileno(), 0) 

obj = ThreeNumbersMMAP(mmap, 0) 
print obj.numbers 
obj.numbers = (1, 2, 3) 
obj.save() 

obj = ThreeNumbersMMAP(mmap, 0) 
print obj.numbers 
obj.numbers = (0, 0, 0) 
obj.save() 
Смежные вопросы