Каков наилучший алгоритм сжатия, который позволяет случайное чтение / запись в файл? - PullRequest
21 голосов
/ 25 октября 2008

Какой наилучший алгоритм сжатия допускает случайное чтение / запись в файл?

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

И я знаю, что о кодировании Хаффмана не может быть и речи.

У кого-нибудь есть лучший алгоритм сжатия, который позволял бы произвольное чтение / запись?

Я думаю, вы можете использовать любой алгоритм сжатия, если пишете его в блоках, но в идеале мне не хотелось бы распаковывать целый блок за раз. Но если у вас есть предложения по простому способу сделать это и как узнать границы блоков, пожалуйста, дайте мне знать. Если это часть вашего решения, пожалуйста, дайте мне знать, что вы делаете, когда данные, которые вы хотите прочитать, выходят за границы блока?

В контексте ваших ответов, предположите, что размер рассматриваемого файла составляет 100 ГБ, и иногда я захочу прочитать первые 10 байтов, а иногда я захочу прочитать последние 19 байтов, а иногда я захочу читать 17 байтов в середине. .

Ответы [ 7 ]

20 голосов
/ 08 августа 2010

Я ошеломлен количеством ответов, которые подразумевают, что такая вещь невозможна.

Разве эти люди никогда не слышали о "сжатых файловых системах", которые существовали с тех пор, как в 1993 году Stac Electronics подала в суд на Microsoft по технологии сжатых файловых систем?

Я слышал, что LZS и LZJB являются популярными алгоритмами для людей, реализующих сжатые файловые системы, которые обязательно требуют как чтения с произвольным доступом, так и записи с произвольным доступом.

Пожалуй, самое простое и лучшее, что можно сделать, - это включить сжатие файловой системы для этого файла и позволить ОС разобраться с деталями. Но если вы настаиваете на том, чтобы справиться с этим вручную, возможно, вы можете воспользоваться некоторыми советами, прочитав о сжатии прозрачных файлов NTFS .

Также проверьте: «StackOverflow: форматы сжатия с хорошей поддержкой произвольного доступа в архивах?»

4 голосов
/ 23 августа 2011

Формат razip поддерживает чтение с произвольным доступом с лучшей производительностью, чем gzip / bzip2, которые необходимо настроить для этой поддержки:

http://sourceforge.net/projects/razip/

3 голосов
/ 30 июля 2010

Я думаю, что Стивен Денн может быть на что-то здесь. Представьте себе:

  • сжатие zip-подобных последовательностей в коды
  • код отображения словаря -> последовательность
  • файл будет похож на файловую систему
    • каждая запись генерирует новый «файл» (последовательность байтов, сжатых по словарю)
    • «файловая система» отслеживает, к какому «файлу» принадлежат какие байты (начало, конец)
    • каждый «файл» сжимается в соответствии со словарем
    • читает работу с файлами, распаковывая и извлекая байты в соответствии с «файловой системой»
    • записи делают "файлы" недействительными, добавляются новые "файлы", чтобы заменить недействительные
  • эта система потребует:
    • механизм дефрагментации файловой системы
    • время от времени сжимая словарь (удаляя неиспользуемые коды)
  • сделано правильно, ведение домашнего хозяйства может быть сделано, когда никто не смотрит (простой) или путем создания нового файла и «переключения» в конечном итоге

Одним положительным эффектом будет то, что словарь будет применяться ко всему файлу. Если вы можете сэкономить циклы ЦП, вы можете периодически проверять последовательности, перекрывающие «файловые» границы, а затем перегруппировать их.

Эта идея предназначена для действительно случайного чтения. Если вы когда-либо собираетесь читать записи фиксированного размера, некоторые части этой идеи могут стать проще.

3 голосов
/ 06 ноября 2008

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

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

1 голос
/ 04 ноября 2008

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

Однако вы можете закрыть для произвольного доступа, сохранив внешний список, созданный во время сжатия, который показывает соответствие между выбранными точками в несжатом потоке данных и их местоположениями в сжатом потоке данных. Очевидно, вам придется выбрать метод, при котором схема трансляции между исходным потоком и его сжатой версией не зависит от местоположения в потоке (т.е. без LZ77 или LZ78; вместо этого вы, вероятно, захотите перейти к Хаффману или байту. парное кодирование.) Очевидно, что это повлечет за собой много накладных расходов, и вам нужно будет решить, каким образом вы хотите обменяться между пространством хранения, необходимым для «точек закладки», и временем процессора, необходимым для распаковки потока, начиная с отметка в закладке, чтобы получить данные, которые вы на самом деле ищете, для этого чтения.

Что касается записи с произвольным доступом ... это почти невозможно. Как уже отмечалось, сжатие заключается в удалении избыточности из данных. Если вы попытаетесь заменить данные, которые могли быть и были сжаты, потому что они были избыточными, на данные, которые не имеют такой же избыточности, они просто не будут соответствовать.

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

1 голос
/ 25 октября 2008

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

например,
Сначала рассмотрим случай только для чтения. Допустим, вы разбили свой файл на 8K кусков. Вы сжимаете каждый фрагмент и сохраняете каждый сжатый фрагмент последовательно. Вам нужно будет записать, где хранится каждый сжатый блок и насколько он велик. Затем, скажем, вам нужно прочитать N байтов, начиная со смещения O. Вам нужно будет выяснить, в каком блоке он находится (O / 8K), распаковать этот блок и захватить эти байты. Данные, которые вам нужны, могут охватывать несколько фрагментов, поэтому вам придется иметь дело с этим сценарием.

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

Это в основном то, как работают сжатые файловые системы. Возможно, вам лучше включить сжатие файловой системы для ваших файлов и просто читать / записывать их в обычном режиме.

0 голосов
/ 25 октября 2008

Никакая схема сжатия не позволит детализировать произвольный доступ по двум связанным причинам:

  • вы не можете точно знать, насколько глубоко в сжатом файле находится желаемый фрагмент данных, поэтому
  • нет способа узнать, где начинается символ (в какой битовой позиции для Хаффмана, хуже для арифметического кодирования).

Я могу только предложить обрабатывать файл как широковещательный поток и вставлять частые маркеры синхронизации / положения с очевидными накладными расходами (метки синхронизации не только сами занимают место, но и усложняют кодирование, поскольку должны избегать «случайных» меток синхронизации !). В качестве альтернативы, и чтобы не искать что-то вроде бинарного поиска (с оптимизацией, с которой вы можете лучше угадать, с чего начать, чем с середины), вы можете включить «оглавление» в начало или конец файла.

Что касается записи с произвольным доступом ... Я не могу придумать ни одного аккуратного решения: (

...