【问题标题】:Reading a binary file bit by bit逐位读取二进制文件
【发布时间】:2012-07-25 16:27:53
【问题描述】:

我知道下面的函数:

size_t fread(void *ptr, size_t size_of_elements, size_t number_of_elements, FILE *a_file);

它只能逐字节读取,我的目标是能够一次读取 12 位,然后将它们放入数组中。任何帮助或指点将不胜感激!

【问题讨论】:

  • 抱歉,一次一个字节是您能做到的最小粒度。您将不得不求助于(不寒而栗)实际编程来拆分 12 位实体。
  • 我想你想要这个答案:stackoverflow.com/questions/141525/…

标签: c file binary bin


【解决方案1】:

添加到第一个注释,您可以尝试一次读取一个字节(声明一个 char 变量并在那里写入),然后使用按位运算符 >> 和 http://www.cprogramming.com/tutorial/bitwise_operators.html

【讨论】:

  • 这就是我要做的,我会让你知道它是如何工作的!非常感谢!!这可能是要走的路!
【解决方案2】:

许多年前,我用 C 语言编写了一些用于 Huffman 编码器的 I/O 例程。这需要能够在位而不是字节的粒度上进行读写。我创建了类似于 read(2) 和 write(2) 的函数,可以要求(比如说)从流中读取 13 位。例如,为了编码,字节将被输入编码器,可变数量的比特将出现在另一端。我有一个简单的结构,其中有一个指向正在读取或写入的当前字节的位指针。每次它结束时,它都会刷新完成的字节并将指针重置为零。不幸的是,该代码早已不复存在,但拆开一个开源的 Huffman 编码器并看看那里的问题是如何解决的可能是一个想法。同样,base64 编码需要 3 个字节的数据,然后将它们变成 4 个字节(反之亦然)。

【讨论】:

  • 每个压缩库都有类似的东西。 ffmpeg/libavutil 中的那个看起来有点可重用。
【解决方案3】:

我已经实现了几种读取/写入文件的方法。 Here 他们是。无论它对您的用例是否可行,您都必须自己决定。我已经尝试制作尽可能可读、优化的代码,而不是经验丰富的 C 开发人员(目前)。

在内部,它使用“bitCursor”来存储有关尚不适合完整字节的先前位的信息。它具有 who 数据字段:d 存储数据,s 存储大小,或存储在光标中的位数。

你有四个功能:

  • newBitCursor(),返回具有默认值的 bitCursor 对象
    {0,0}。在一个序列的开头需要这样一个光标 对文件进行读/写操作。
  • fwriteb(void *ptr, size_t sizeb, size_t rSizeb, FILE *fp, bitCursor *c),它将存储在 ptr 中的值的 sizeb 个最右边的位写入 fp。
  • fcloseb(FILE *fp, bitCursor *c),写入剩余字节,如果 之前的写入并没有完全封装所有需要的数据 写,可能几乎总是这样......
  • freadb(void *ptr, size_t sizeb, size_t rSizeb, FILE *fp, bitCursor *c),它读取 sizeb 位并将它们按位 ORs 到 *ptr。 (因此,您有责任将 *ptr 初始化为 0

cmets 中提供了更多信息。玩得开心!

编辑:It has come to my knowledge 今天,当我做出那个时,我假设是小尾数! :P 哎呀!意识到我仍然是一个菜鸟总是很高兴;D。

编辑:GNU's Binary File Descriptors

【讨论】:

    【解决方案4】:

    从您的 a_file 文件指针中读取前两个字节,并检查最小或最大字节中的位 - 取决于您的平台的 endianness(x86 是小端) - 使用位移运算符。

    您不能真正将位放入数组中,因为位没有数据类型。与其将 1 和 0 保存在一个效率低下的数组中,不如将这两个字节保存在一个二元素数组中(例如,unsigned char * 类型)并编写函数将这两个字节映射到 4096 中的一个似乎更便宜(2^12) 个感兴趣的值。

    作为一种复杂情况,在后续读取中,如果您希望每 12 位通过指针fread,您将只读取 一个 字节,使用上次读取的剩余位建立一个新的 12 位值。如果没有剩余,则需要读取两个字节。

    您的映射函数需要解决第二种情况,即使用先前读取的位,因为这两个字节需要不同的映射。为了有效地做到这一点,可以使用读取计数器上的模数在两个映射之间进行交换。

    【讨论】:

      【解决方案5】:

      读取 2 个字节并执行按位操作将在下一次读取第 2 个字节时完成,应用按位操作将返回您预期的结果。 . . .

      【讨论】:

        【解决方案6】:

        对于您的问题,您可以看到这个演示程序,它读取 2 字节,但实际信息只有 12 位。以及这种类型的东西被使用它按位访问。

        fwrite() 是一个标准库函数,它将大小参数作为字节和 int 类型。因此不可能完全读取 12 位。如果您创建的文件也像下面一样创建如下阅读它可以解决您的问题。

        如果该文件是不是由您编写的特殊文件,那么请按照为该文件提供的标准进行读取,我认为他们也只能这样写。或者您可以提供我可以帮助您的地方。

        #include<stdio.h>
        #include<stdlib.h>
        struct node
         {
           int data:12;
        
         }NODE;
        int main()
        {
           FILE *fp;
           fp=fopen("t","w");
           NODE.data=1024;
           printf("%d\n",NODE.data);
           fwrite(&NODE,sizeof(NODE),1,fp);
           NODE.data=0;
           NODE.data=2048;
           printf("%d\n",(unsigned)NODE.data);
           fwrite(&NODE,sizeof(NODE),1,fp);
           fclose(fp);
           fp=fopen("t","r");
           fread(&NODE,sizeof(NODE),1,fp);
           printf("%d\n",NODE.data);
           fread(&NODE,sizeof(NODE),1,fp);
           printf("%d\n",NODE.data);
           fclose(fp);
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-12-06
          • 1970-01-01
          • 1970-01-01
          • 2012-07-11
          • 1970-01-01
          • 2017-11-27
          相关资源
          最近更新 更多