Простое сжатие ASCII - помогает минимизировать системные вызовы - PullRequest
0 голосов
/ 22 февраля 2011

В моем последнем вопросе nos дал метод удаления наиболее значимого бита из символьного байта ASCII, который в точности соответствует тому, что сказал мой профессор при описании проекта.

Моя проблема заключается в том, как убрать значащий бит и упаковать его в буфер, используя команды read и write.Поскольку команда write требует длины в количестве байтов для записи, как мне перейти к уровню битов в массиве буферов?

Ответы [ 3 ]

3 голосов
/ 22 февраля 2011

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

Давайте назовем входные данные input[0..7] и выходные данные output[0..6].

Итак, первый байт выводаданные output[0] состоят из 7 младших битов input[0] плюс второй старший бит input[2].Это работает одинаково для всех остальных:

    Index:    [0]      [1]      [2]      [3]      [4]      [5]      [6]      [7]
    Input:  0aaaaaaa 0bbbbbbb 0ccccccc 0ddddddd 0eeeeeee 0fffffff 0ggggggg 0hhhhhhh
            ///////  //////   and     --->
            ||||||| /|||||     so on  --->
    Output: aaaaaaab bbbbbbcc cccccddd ddddeeee eeefffff ffgggggg ghhhhhhh
    Index:    [0]      [1]      [2]      [3]      [4]      [5]      [6]

Вы можете использовать такие операции, как:

output[0] = ((input[0] & 0x7f) << 1) | ((input[1] & 0x40) >> 6)
output[1] = ((input[1] & 0x3f) << 2) | ((input[2] & 0x60) >> 5)
:
output[5] = ((input[5] & 0x03) << 6) | ((input[6] & 0x7e) >> 1)
output[6] = ((input[6] & 0x01) << 7) |  (input[7] & 0x7f)

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

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

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

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

2 голосов
/ 22 февраля 2011

Как говорит Паксдиабло: самый простой способ сделать это - куски по восемь байт. Но зачем сдвигать 8 байт? Вы можете упаковать в первые 7 байтов биты последнего байта! Просто и быстро ...

Output[0] = ((Input[0] & 0x7f) | (Input[7] & 0x80))         //pack 7th bit in 0th byte
Output[1] = ((Input[1] & 0x7f) | ((Input[7] << 1) & 0x80))  //pack 6th bit in 1th byte
Output[2] = ((Input[2] & 0x7f) | ((Input[7] << 2) & 0x80))  //pack 5th bit in 2th byte
...

Для восстановления просто сложите 7-й бит из всех 7 байтов в 7-й и очистите 7-й бит во всех байтах массива.

1 голос
/ 22 февраля 2011

Сначала вам нужно упаковать данные в буфер в памяти. Например, чтобы было проще:

unsigned char unpacked[128];  // read file input into this buffer
unsigned char packed[128];    // copy from unpacked to here while compressing
                              // then write() this to output file...

Чтобы выполнить само сжатие, вам необходимо выполнить цикл по количеству байтов, считанных в unpacked, и использовать побитовые операторы, такие как & (поразрядное И), | (поразрядное ИЛИ), << поразрядное влево смещение.

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

...