web-dev-qa-db-ja.com

Cでファイルにビットを書き込む

「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);

しかし、最後に、ファイルのバイト数を確認すると、4バイトのファイルであるとWindowsから言われます。 3ビットではありません!

可能であれば、どうすればこれを実行できますか?どうもありがとう。

26

すべてのファイルシステムは、バイト単位でファイルを扱います(そして、最小で512バイトのはるかに大きな粒度でストレージ領域を割り当てます)。 ビット長いファイルを取得する方法はありません。

最善の方法は、1バイト全体を使い切ることですが、そのビットの5つは無視してください。これを行うには(数値が常にバイトに収まると仮定)、入力文字列を整数型に変換します。

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

次に、最下位バイトを取得します。

unsigned char b = l & 0xffl;

そしてそれをファイルに書き込みます:

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

¹まあ、すべてではないかもしれません。ビットサイズのファイルシステムを実験する研究者がどこかにいるかもしれません。分からない。

33
Jon

intをファイルに書き込んでいるため、出力ファイルの長さは4バイトです。ほとんどのプラットフォームでは、intのサイズは4バイトです。

一度に1バイト未満を書き込むことはできません。

14
jbowes

あなたができることは、それをビット(3)として書き込み、1バイトまで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
Michel Keijzers

あなたのアプローチに関する2つのメモ:

  1. [モダン]コンピュータはメモリ内で1バイト未満を処理できないため、ディスクに単一ビットを書き込むことができません。

    また、ファイルシステムは通常、ファイルが収まる場所にチャンク(512バイト、1Kb、...)でスペースを割り当てます。したがって、500バイトのファイルがある場合、実際には512バイトのディスク領域が失われています。

  2. atoi()は、文字列から2進数に変換するのではなく、整数に変換します。あなたは実際に書いています0b1100101、つまり0d101。最初に変換を行う必要があります。何かのようなもの:

    char b = 0;
    for (int i=0; c[i]!=NULL; i++) 
    {
        b = ((b<<1) | atoi(c[i]));
    }
    
5
J.A.I.L.

ビット_101_ではなく、10進数のバイナリ値_101_、つまり_1100101_を書き込んでいます。あなたはfread _sizeof(x)バイトのサイズなので、ファイルはsizeof(x)バイトの長さになります。

3
md5