Текущий проект в системном программировании заключается в создании компрессора 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 байтам.
Я получаю те же шестнадцатеричные коды из распечатки, которые я предварительно обработал в двоичном формате, и я вижу верхний бит каждого байта. Так почему же сдвиги не отражаются на результатах?