Сжатие UTF-8 (или другого 8-битного кодирования) до 7 или менее бит

Я хочу взять файл, закодированный в UTF-8, который не использует более 128 разных символов, а затем переместит его в 7-битную кодировку, чтобы сохранить 1/8 пробела. Например, если у меня есть текстовый файл размером 16 МБ, который использует только первые 128 (ascii) символов, я бы хотел сбрить дополнительный бит, чтобы уменьшить файл до 14 МБ.

Как мне это сделать?

Кажется, что нет существующей бесплатной или проприетарной программы, поэтому я думал, что могу попытаться сделать простой (если неэффективный).

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

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

127 254 025 212 015 015 132 … Это станет

001 002 003 004 005 005 006

Если 127 отображается на 001, 254 – на 005 и т. Д.

Тем не менее, я не совсем уверен в некоторых вещах.

  1. Будет ли этого достаточно, чтобы фактически сократить размер файла? У меня плохое чувство, что это просто оставит лишний 0 в двоичной строке – 11011001 может быть сопоставлен с 01000001, а не с 1000001, и я фактически не буду экономить место. Если это произойдет, как мне избавиться от нуля?
  2. Как открыть файл для чтения / записи в двоичном / десятичном / шестнадцатеричном формате, а не только в тексте? Я в основном работал с Python, но я могу запутаться через C, если нужно.

Спасибо.

Просто используйте сжатие gzip и сэкономьте 60-70% при напряжении 0%!

Вы понимаете, что файлы делятся на байты? Таким образом, если вы это сделали, у вас будет 7 бит первой буквы в байтах 1 плюс 1 бит второй буквы, а затем в байте два, у вас будет 6 бит второй буквы и 2 бита в-третьих, и так далее. Это будет выглядеть так:

|AAAAAAAB|BBBBBBCC|CCCCCDDD|DDDDEEEE|EEEFFFFF|FF... \------/ \------/ \------/ \------/ \------/ byte byte byte byte byte 

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

Я могу рекомендовать книгу сжатия данных Марка Нельсона, которая представляет собой отличное введение в методы сжатия данных.

Ваша идея вряд ли сработает. Если вы напишете байт 0x05 в файл, байт будет записан, все 8 бит его – с ведущими нулями. Чтобы выполнить то, что вам нужно, вы можете кодировать каждые 8 ​​байтов в 7 байтах (поскольку для кодирования 8 значений требуется всего 8 * 7 бит). Один из подходов состоит в том, чтобы сохранить 7 значений в 7 младших бит своих байтов и распределить 8-й байт над 7 MSBits.

Что касается Python, открывается файл в двоичном режиме записи open(filename, 'wb') . Вам также нужно будет узнать о битовых операциях для пакетных байтов, как описано выше.

Небольшой пример:

 >>> a = 0x03 >>> b = 0x59 >>> c = ((a & 0x1) << 7) | b >>> hex(c) '0xd9' >>> 

Это помещает младший бит a в MSBit c а остальная часть c – значение b .

Я уверен, что вы можете взять это отсюда.

«это просто оставит дополнительное 0 в двоичной строке – 11011001 может быть отображено на 01000001, а не на 1000001, и я фактически не сэкономлю место».

Верный. Ваш план ничего не сделает.

Вам нужен UTF-7.

Изменить: UTF-7 имеет преимущество раздувания «только» специальных символов, поэтому, если специальные символы встречаются редко на входе, вы получаете гораздо меньше байтов, чем просто конвертируя UTF-8 в 7 бит. Это то, что для UTF-7.