在C语言中向文件写入位(bit)

29

我有这个字符串:"101",我想在C语言中将其写入文件,不是作为文本:"101",而是直接使用字符串作为位:"1"位、"0"位和"1"位,使得文件将会是3位。

这种方式可行吗?我在网上搜索并尝试了以下代码:

char c[25] = "101";
FILE *binFile = fopen("binFile.bin", "wb");
int x = atoi(c);
fwrite(&x, sizeof(x), 1, binFile);

但最终当我验证文件的字节时,Windows告诉我这是一个4字节的文件!而不是3位!

如果可能的话,我该怎么做?非常感谢。


我认为这里应该是“WORD”(字).. http://en.wikipedia.org/wiki/Word_(computer_architecture) - Chad Harrison
1
“变量字体结构”这一部分可能会特别吸引您的注意。 - Chad Harrison
5个回答

36

所有文件系统¹都以字节为单位处理文件(并使用更大的粒度分配存储空间,最小512个字节)。你永远不可能得到一个长度为3位的文件。

你能做的最好的事情是使用整个字节,但忽略其中的5个位。为了做到这一点(假设该数字始终适合一个字节),将输入字符串转换为整数类型:

long l = strtol(c, 0, 2);

然后获取它的最低有效字节:

unsigned char b = l & 0xffl;

然后将其写入文件:

fwrite(&b, 1, 1, binFile);

¹好吧,也许不是所有的研究人员都会尝试使用比特大小的文件系统。可能还有一些地方我不知道。



1
我猜他将会写很多个单独的位,为了最终压缩,他可以创建一个缓冲版本的fwrite(),一旦填满就会一次性刷新整个字节。 - Benj

15

你的输出文件长度为4个字节,因为你正在将一个int写入文件。在大多数平台上,int的大小为4个字节。

你无法一次写入少于1个字节。


7
你可以将其写成位(3),并用0填充到一个字节。但是,你还需要以使用的位数(或最后一个字节中的位数)为开头(或结尾)。例如(使用第一个字节作为长度):
00000011   -> 3, meaning from the last (and only byte in this case, 
              only the first 3 bits are used)
10100000   -> 101 is the string, other 5 bits are 0, just use for padding

在这种情况下,第一个(长度)字节的开销为50%,字符串越长,开销百分比当然越少。

6

关于你的方法,我有两点建议:

  1. [Modern] Computers can't handle less than 1 byte in memory, so you won't be able to write single bits to disk.

    Also, filesystems usually allocate space in chunks (512 bytes, 1Kb, ...) where the file fits. So, if you have a 500 bytes file, you are actually loosing 512 bytes of disk space.

  2. atoi() doesn't convert from string to binary numbers, but to integer. You are actually writing 0b1100101, which is 0d101. You should do the conversion first. Something like:

    char b = 0;
    for (int i=0; c[i]!=NULL; i++) 
    {
        b = ((b<<1) | atoi(c[i]));
    }
    

4

您不是在写二进制位101,而是十进制数101的二进制值,即1100101。因为您使用fread读取了sizeof(x)字节的大小,所以您的文件将会有sizeof(x)字节长。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接