0

我需要解压缩一个二进制文件。由于二进制文件以 14 位编码,因此我必须读取 14 位而不是 8 位来解码。但据我所知,使用getc()读取文件每次只给我 8 位。有没有有效的方法来实现这一目标?下面是一个可以完成这项工作的代码块,但它似乎效率不高,我该如何改进它?

unsigned int input_code(FILE *input)
{
    unsigned int return_value;
    static int input_bit_count=0;
    static unsigned long input_bit_buffer=0L;

    while (input_bit_count <= 24)
    {
        input_bit_buffer |= 
            (unsigned long) getc(input) << (24-input_bit_count);
        input_bit_count += 8;
    }

    return_value=input_bit_buffer >> (32-BITS);
    input_bit_buffer <<= BITS;
    input_bit_count -= BITS;
    return(return_value);
}
4

3 回答 3

4

一般来说,您应该避免读取如此少量的数据,因为它效率低下,尽管标准库和 O/S 内部的缓冲代码会弥补这一点。

更好的理由是它可能导致奇怪和不自然的代码。为什么不一次读取 112 位 = 14 个字节 - 这是 8 的倍数和 14 的倍数。然后您可以将生成的缓冲区视为 8 个 14 位数据。所以事情进展顺利。

但是,如果您绝对必须一次读取尽可能少的字节,则读取 16 位,然后吃掉(即处理)其中的 14 个,再读取 16 个,将它们与您已经读取的 2 个结合起来,吃掉 14 个,然后重复这个过程. 有关如何执行此类操作的提示,请查看 base64 编码器/解码器。

于 2013-03-22T23:29:36.667 回答
1

每个输入/输出 char 或 int 的几条指令的开销很可能可以忽略不计。除非您在这里发现瓶颈,否则不要尝试优化这段代码。

此外,如果我是你,我会检查getc(). 它可以返回EOF而不是数据。

此外,严格来说,char(或 C 的字节)中有CHAR_BIT位,可以大于 8。

于 2013-03-22T23:23:15.540 回答
0

您一次不能读取少于一个字节。但是,您可以使用位掩码和移位操作将最后两位设置为0(如果您存储 16),并携带您删除的两个未使用位作为下一个值。不过,这可能会使解码操作更加复杂和昂贵。

如何将 8 乘 8 的值解码(您可以读取 14 个字符 = 112 位 = 8 * 14 位)?我没有测试过这段代码,里面可能有一些错别字。它确实编译但我没有你的文件来测试它:

#include <stdio.h>

int main(){
    FILE *file = fopen ("...", "rt");

    // loop variable
    unsigned int i;

    // temporary buffer
    char buffer[14];

    // your decoded ints
    int decoded[8];

    while(fgets(buffer, 14, file) != NULL) {
        int cursor = 0;

        // we do this loop only twice since the offset resets after 4 * 14
        for(i = 0; i <= 4; i+= 4){
            // first decoded int is 16 bits
            decoded[i+0] = (buffer[cursor++] | (buffer[cursor++] << 8));
            // second is 2 + 8 + 8 = 18 bits (offset = 2)
            decoded[i+1] = (decoded[i+0] >> 14) | buffer[cursor++] << 2 | buffer[cursor++] << 10;
            // third is 4 + 8 + 8 = 20 bits (offset = 4)
            decoded[i+2] = (decoded[i+1] >> 14) | buffer[cursor++] << 4 | buffer[cursor++] << 12;
            // next is 6 + 8 = 14 bits (offset = 6)
            decoded[i+3] = (decoded[i+2] >> 14) | buffer[cursor++] << 6;
        }

        // trim the numbers to 14 bits
        for(i = 0; i < 8; ++i)
            decoded[i] &= ((1 << 15) - 1);
    }
    fclose(file);
}

请注意,我对解码后的整数不做任何事情,我一遍又一遍地在同一个数组上写入,这只是一个说明。您可以对代码进行更多分解,但我展开了循环并注释了操作,以便您了解它是如何工作的。

于 2013-03-22T23:26:09.027 回答