将位写入文件?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了将位写入文件?相关的知识,希望对你有一定的参考价值。

我正在尝试实现一个霍夫曼树。

我想做一个简单测试的简单.txt文件的内容:

aaaaabbbbccd

字符频率:a:5,b:4,c:2,d:1

代码表:(数据类型为1和0:字符串)

a:0
d:100
c:101
b:11         

我想写成二进制文件的结果:(22位)

0000011111111101101100          

如何将此结果的每个字符逐位写为“.dat”文件的二进制文件? (不是字符串)

答案

OP问道:

如何将此结果的每个字符逐位写为“.dat”文件的二进制文件? (不是字符串)

你不能,这就是为什么......


记忆模型

为C ++抽象机器定义计算机内存存储的语义。

C ++程序可用的内存是bytes的一个或多个连续序列。内存中的每个字节都有一个唯一的地址。

字节

byte是最小的可寻址存储单元。它被定义为一个连续的位序列,大到足以保存任何UTF-8代码单元的值(256个不同的值)和(since C++14)的基本执行字符集的任何成员(需要为single-byte的96个字符) 。与C类似,C ++支持大小为8位或更大的bytes

类型charunsigned charsigned char使用一个字节用于存储和值表示。可以通过CHAR_BITstd::numeric_limits<unsigned char>::digits访问字节中的位数。

赞美cppreference.com

你可以在这里找到这个页面:cppreference:memory model


这来自2017-03-21:标准

©ISO / IEC N4659

4.4 C ++内存模型[intro.memory]

  1. C ++内存模型中的基本存储单元是字节。一个字节至少足以包含基本执行字符集(5.3)的任何成员和Unicode UTF-8编码形式的八位代码单元,并由一个连续的位序列组成,4其数量为是实现定义的。最低有效位称为低位;最重要的位称为高位。 C ++程序可用的内存由一个或多个连续字节序列组成。每个字节都有一个唯一的地址。
  2. [注意:类型的表示在6.9中描述。 - 尾注]
  3. 存储器位置是标量类型的对象或者具有非零宽度的相邻位域的最大序列。 [注意:该语言的各种功能,例如引用和虚函数,可能涉及程序无法访问但由实现管理的其他内存位置。 -end note]两个或多个执行线程(4.7)可以访问不同的内存位置而不会相互干扰。
  4. [注意:因此,位字段和相邻的非位字段位于不同的存储器位置中,因此可以通过两个执行线程同时更新而不会产生干扰。这同样适用于两个位字段,如果一个在嵌套的结构声明中声明而另一个未声明,或者两者是由零长度位字段声明分隔,或者它们是由非位分隔 - 现场声明。如果它们之间的所有字段也是非零宽度的位字段,则同时更新同一结构中的两个位字段是不安全的。 - 尾注]
  5. [示例:声明为的结构 struct { char a; int b:5, c:11, :0, d:8; struct {int ee:8;} e; } 包含四个独立的存储器位置:字段a和位字段d和e.ee是每个单独的存储器位置,并且可以同时修改而不会相互干扰。位域b和c一起构成第四存储器位置。位域b和c不能同时修改,但b和a例如可以。 - 末端的例子] 4)字节<climits>中的宏CHAR_BIT报告一个字节中的位数。

这个版本的标准可以在这里找到:www.open-std.org部分§ 4.4在第8和9页。


对于标准字节,可以在程序中写入的最小可能存储器模块是8个连续位或更多位。即使有位字段,1 byte要求仍然有效。你可以在byte中操纵,切换,设置各个位,但你不能写单个bits

可以做的是使用一个写入位数的byte缓冲区。写入所需的位后,您需要将剩余的未使用位标记为paddingun-used buffer bits

编辑

[注意:] - 当使用bit fieldsunions时,你必须考虑的一件事是特定架构的endian

另一答案

答:你不能。

您可以写入文件(或从中读取)的最小金额是charunsigned char。出于所有实际目的,char只有8位。

您将需要一个char缓冲区,以及它所拥有的位数的计数。当该数字达到8时,您需要将其写出,并将计数重置为0.您还需要一种方法来在最后刷新缓冲区。 (并不是说您不能将22位写入文件 - 您只能写入16或24.您需要一些方法来标记末尾的哪些位未被使用。)

就像是:

struct BitBuffer {
    FILE* file; // Initialization skipped.
    unsigned char buffer = 0;
    unsigned count = 0;

    void outputBit(unsigned char bit) {
         buffer <<= 1;         // Make room for next bit.
         if (bit) buffer |= 1; // Set if necessary.
         count++;              // Remember we have added a bit.
         if (count == 8) {
             fwrite(&buffer, sizeof(buffer), 1, file); // Error handling elided.
             buffer = 0;
             count = 0;
         }
    }
};

以上是关于将位写入文件?的主要内容,如果未能解决你的问题,请参考以下文章

向/从文件写入/读取位域结构

Java BitSet 和 byte[] 用法

记录C#常用的代码片段

如何将这个 Objective-C 代码片段写入 Swift?

通过连接将位(字节)存储在 long long 中

将 XSLT 转换的 XML 片段写入 XMLStreamWriter