Компрессор ASCII работает для коротких тестовых файлов, а не для длинных - PullRequest
6 голосов
/ 05 марта 2011

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

Для облегчения распаковки в файл записывается исходный размер файла, а затем сжатые байты символов. Есть два файла для запуска тестов, один из которых имеет длину 63 байта, а другой - 5344213 байта. Приведенный ниже код работает, как и ожидалось, для первого тестового файла, поскольку он записывает 56 байтов сжатого текста плюс 4 байта заголовка файла.

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

while ( (characters= read(openReadFile, unpacked, BUFFER)) >0 ){
   unsigned char packed[7]; //compression storage
   int i, j, k, writeCount, endLength, endLoop;

    //loop through the buffer array
    for (i=0; i< characters-1; i++){
        j= i%7; 

        //fill up the compressed array
        packed[j]= packer(unpacked[i], unpacked[i+1], j);

        if (j == 6){
            writeCalls++; //track how many calls made

            writeCount= write(openWriteFile, packed, sizeof (packed));
            int packedSize= writeCount;
            for (k=0; k<7 && writeCalls < 10; k++)
                printf("%X ", (int)packed[k]);      

            totalWrittenBytes+= packedSize;
            printf(" %d\n", packedSize);
            memset(&packed[0], 0, sizeof(packed)); //clear array

            if (writeCount < 0)
                printOpenErrors(writeCount);
        }
        //end of buffer array loop
        endLength= characters-i;
        if (endLength < 7){

            for (endLoop=0; endLoop < endLength-1; endLoop++){
                packed[endLoop]= packer(unpacked[endLoop], unpacked[endLoop+1], endLoop);
            }

            packed[endLength]= calcEndBits(endLength, unpacked[endLength]);
        }
    } //end buffer array loop
} //end file read loop

Функция упаковщика:

//calculates the compressed byte value for the array
char packer(char i, char j, int k){
    char packStyle;

    switch(k){
        //shift bits based on mod value with 8
        case 0:
                packStyle= ((i & 0x7F) << 1) | ((j & 0x40) >> 6);
            break;
        case 1:
            packStyle= ((i & 0x3F) << 2) | ((j & 0x60) >> 5);
            break;
        case 2:
            packStyle= ((i & 0x1F) << 3) | ((j & 0x70) >> 4);
            break;
        case 3:
            packStyle= ((i & 0x0F) << 4) | ((j & 0x78) >> 3);
            break;
        case 4:
            packStyle= ((i & 0x07) << 5) | ((j & 0x7C) >> 2);
            break;
        case 5:
            packStyle= ((i & 0x03) << 6) | ((j & 0x7E) >> 1);
            break;
        case 6:
            packStyle= ( (i & 0x01 << 7) | (j & 0x7F));
            break;
    }

    return packStyle;
}

Я проверил, что при каждом сбросе упакованного буфера записывается 7 байтов, и для длинного файла было сделано 763458 вызовов записи, которые соответствуют записанным 5344206 байтам.

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

Ответы [ 2 ]

1 голос
/ 05 марта 2011

Хорошо, так как это домашнее задание, я просто дам вам несколько советов, не предлагая решения.

Во-первых, вы уверены, что 56 байтов, которые вы получаете в первом файле, являются правильными? Конечно, счет выглядит хорошо, но вам повезло на счет (доказательство - второй тестовый файл). Я сразу вижу как минимум две ключевые ошибки в коде.

Чтобы убедиться, что у вас есть правильный вывод, количество байтов недостаточно. Тебе нужно копать глубже. Как насчет проверки самих байтов один за другим. 63 символа не так много, чтобы пойти хе? Есть много способов сделать это. Вы можете использовать od (довольно хороший инструмент Linux / Unix для просмотра двоичного содержимого файлов, если вы используете Windows, используйте какой-нибудь Hex-редактор). Или вы можете распечатать отладочную информацию из вашей программы.

Удачи.

0 голосов
/ 05 марта 2011

Почему вы ожидаете, что выходной сигнал будет на 14% короче входного?Как это может быть, когда вы сохраняете байт в упакованном столько раз, сколько есть входных байтов, кроме последней группы?Размер вывода всегда будет в пределах 7 от размера ввода.

...