ASCII压缩器适用于短测试文件,而不是长时间

时间:2011-03-05 04:00:12

标签: c compression bit-manipulation

系统编程中的当前项目是提出一个ASCII压缩器,它删除顶部零位并将内容写入文件。

为了便于解压缩,将原始文件大小写入文件,然后压缩char字节。有两个文件可以运行测试 - 一个是63字节长,另一个是5344213字节。我的代码在第一个测试文件中按预期工作,因为它写入56个字节的压缩文本和4个字节的文件头。

但是,当我在长测试文件上尝试它时,压缩版本比原始版本短3个字节,当它应该大约小749KiB,或原始大小的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 个答案:

答案 0 :(得分:1)

好的,既然这是家庭作业,我会给你一些提示而不给出解决方案。

首先,您确定第一个文件中的56个字节是正确的字节吗?当然计数看起来很好,但你算得上很幸运(证明是第二个测试文件)。我可以立即在代码中看到至少两个关键错误。

为确保输出正确,字节数不足。你需要深入挖掘。如何逐个检查字节本身。嘿,63个字符不是很多吗?有很多方法可以做到这一点。你可以使用od(一个非常好的Linux / Unix工具来查看文件的二进制内容,如果你在Windows上使用一些Hex编辑器)。或者您可以从程序中打印出调试信息。

祝你好运。

答案 1 :(得分:0)

为什么期望输出比输入短14%?怎么可能,当你将一个字节存储到打包中的次数与输入字节一样多,除了最后一个组?输出的大小始终在输入大小的7之内。