【问题标题】:Having issues writing and reading binary from a .bin file从 .bin 文件写入和读取二进制文件时遇到问题
【发布时间】:2022-01-22 09:45:46
【问题描述】:

我正在使用 Huffman 算法开发一个编码/解码程序。将树写入文件效果很好,但是在编写编码字符时遇到了问题。由于某种原因,如果一个字节的所有位都设置为 1,它会停止打印到文件。

不起作用的示例是使用以下编码:

String: AAAAACCEEEEEEEEKDDDD

A: 10
C: 1101
D: 111
E: 0
K: 1100

这给出了编码字符串:

101010101011011101000000001100111111111111

这个编码字符串存储在一个无符号字符数组中。

在编码字符之前,我有 4 个字节,其中包含一个 unsigned long int,它表示被解码的字符数量。并且树本身被放置在编码位之前。

正在打印的位的全长如下:

00000000 00000000 00000000 00010100 01010001 01010100 00010010 10010111 01000011 
10100010 01010101 01011011 10100000 00011001 11111111 11100000

我的问题在于将此编码字符串写入 .bin 文件。由于某种原因,它在一个带有八个 1 的字节后停止写入。例如,我尝试过更改字符串,使其不会以只有 1 的字符结尾,并且效果很好。

我如何写入文件:

int main(void)
{
   FILE *output = fopen("filename.bin", "wb");
   unsigned char array[] = {0, 0, 0, 20, 81, 84, 18, 151, 67, 162, 
                            85, 91, 160, 25, 254, 224};
   int size = 16;
   write_to_file(array, size, output);
   return 0;
}

void write_to_file(const unsigned char *array, const int size, FILE *output)
{
   fwrite(array, sizeof(char), size, output);
}

我是如何阅读文件的:

int main(void)
{
   FILE *input = fopen("filename.bin", "r");
   read_file(input);
   return 0;
}

void read_file(FILE *input)
{
   unsigned long int num;
   fread(&num, sizeof(unsigned long int), 1, input);

   char c;
   while((c = fgetc(input)) != EOF){
      for(int i = 0; i < 8; i++){
         int bit = !!((c << i) & 0x80);

         do_something_with_bit(bit);
      }
   }
}

我尝试在 char 和 unsigned char 之间进行更改,因为我认为它是一个负字符是一个问题,但它并没有改变结果。

我看不出它为什么不起作用的原因,但我已经用尽了我能想出的所有可能的解决方案,而且我在文档中看不到任何关于这不可能的信息。任何线索为什么这不起作用?我是否错误地写入/读取信息?谢谢!

【问题讨论】:

  • 不是问题,但可能是未来的问题:使用rb,而不是r 打开二进制文件,就像您使用wb 编写它一样。

标签: c file binary huffman-code


【解决方案1】:

问题出在这里:

char c;
while((c = fgetc(input)) != EOF){

c的定义改为int c;

fgetc 返回一个int,而不是 char,但c 不能包含int 的所有值。当fgetc 读取一个字符时,它会将该字符的代码作为unsigned char 返回(因此您不应使用char 类型来保存这些值)。当它遇到错误或文件结束时,它返回EOF

EOF 通常为 -1,尽管它可以是由 C 实现确定的另一个负值。当fgetc 读取一个全为 1 位的 8 位字节字符时,它返回 255。当 255 分配给带符号的 8 位 char 时,该值被转换。转换是实现定义的,但它通常包装模 256。这意味着,对于声明为 charc,赋值 c = 255c 设置为 -1。然后c == EOF 为真,您的循环停止。

【讨论】:

  • 哇哦!这很有意义。非常感谢您的帮助,非常感谢!
猜你喜欢
  • 1970-01-01
  • 2017-09-01
  • 1970-01-01
  • 1970-01-01
  • 2013-05-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多