29

我有这个字符串:“101”我想把它写到一个文件中,用 C 语言,而不是文本:“101”等等 8 位 x 字符。但直接将字符串用作位:位“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 告诉我它是 4bytes 文件!而不是3位!

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

4

5 回答 5

36

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

您能做的最好的事情就是用完一个完整的字节,但忽略其中的 5 个位。为此(假设数字总是适合一个字节),请将输入字符串转换为整数类型:

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

然后得到它的最低有效字节:

unsigned char b = l & 0xffl;

并将其写入文件:

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

¹好吧,也许不是全部。可能有一些研究人员在某处试验位大小的文件系统。我不会知道的。

于 2012-11-06T14:06:55.217 回答
15

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

您一次不能写入少于 1 个字节。

于 2012-11-06T14:07:52.270 回答
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%,字符串越长,开销百分比当然越小。

于 2012-11-06T14:08:57.923 回答
6

关于您的方法的 2 个注意事项:

  1. [现代] 计算机无法处理小于 1 字节的内存,因此您将无法将单个位写入磁盘。

    此外,文件系统通常以适合文件的块(512 字节,1Kb,...)分配空间。所以,如果你有一个 500 字节的文件,你实际上会失去 512 字节的磁盘空间。

  2. atoi()不会从字符串转换为二进制数,而是转换为整数。你实际上是在写作0b1100101,也就是0d101。您应该先进行转换。就像是:

    char b = 0;
    for (int i=0; c[i]!=NULL; i++) 
    {
        b = ((b<<1) | atoi(c[i]));
    }
    
于 2012-11-06T14:31:50.927 回答
4

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

于 2012-11-06T14:11:13.843 回答