Удалить / вставить данные в файл mmap - PullRequest
5 голосов
/ 07 мая 2011

Я работаю над сценарием на Python, который отображает файл для обработки с помощью mmap ().

Для выполнения этих задач требуется изменить содержимое файла на

  1. Замена данных
  2. Добавление данных в файл со смещением
  3. Удаление данных из файла (не выбрасывая их)

Замена данных прекрасно работает до тех пор, пока старые данныеи новые данные имеют такое же количество байтов:

VDATA = mmap.mmap(f.fileno(),0)
start = 10
end = 20
VDATA[start:end] = "0123456789"

Однако, когда я пытаюсь удалить данные (заменив диапазон на "") или вставив данные (заменив диапазон содержимым, длина которого превышает диапазон), Я получаю сообщение об ошибке:

IndexError: назначение фрагмента mmap неправильного размера

Это имеет смысл.

Теперь вопрос в том, как можноВставить и удалить данные из файла mmap?Из прочтения документации кажется, что я могу перемещать все содержимое файла назад и вперед, используя цепочку низкоуровневых действий, но я бы предпочел этого избежать, если есть более простое решение.

Ответы [ 2 ]

6 голосов
/ 09 мая 2011

В отсутствие альтернативы я написал две вспомогательные функции - deleteFromMmap () и insertIntoMmap () - для обработки действий с файлами низкого уровня и упрощения разработки.

Закрытие и повторное открытиеmmap вместо использования resize () - это ошибка в python на unix-производных, приводящая к сбою resize ().(http://mail.python.org/pipermail/python-bugs-list/2003-May/017446.html)

Функции включены в полный пример. Использование глобального связано с форматом основного проекта, но вы можете легко адаптировать его под свои стандарты кодирования.

import mmap

# f contains "0000111122223333444455556666777788889999"

f = open("data","r+")
VDATA = mmap.mmap(f.fileno(),0)

def deleteFromMmap(start,end):
    global VDATA
    length = end - start
    size = len(VDATA)
    newsize = size - length

    VDATA.move(start,end,size-end)
    VDATA.flush()
    VDATA.close()
    f.truncate(newsize)
    VDATA = mmap.mmap(f.fileno(),0)

def insertIntoMmap(offset,data):
    global VDATA
    length = len(data)
    size = len(VDATA)
    newsize = size + length

    VDATA.flush()
    VDATA.close()
    f.seek(size)
    f.write("A"*length)
    f.flush()
    VDATA = mmap.mmap(f.fileno(),0)

    VDATA.move(offset+length,offset,size-offset)
    VDATA.seek(offset)
    VDATA.write(data)
    VDATA.flush()

deleteFromMmap(4,8)

# -> 000022223333444455556666777788889999

insertIntoMmap(4,"AAAA")

# -> 0000AAAA22223333444455556666777788889999
2 голосов
/ 07 мая 2011

Нет способа сдвинуть содержимое файла (будь то mmap или просто), не делая этого явно.В случае файла mmap вам нужно будет использовать метод mmap.move.

...