Escribir bits en un archivo en C


Tengo esta cadena: "101" Quiero escribirlo en un archivo, en C, no como texto:" 101 " y así 8 bits x char. pero utilice directamente la cadena como bits: el bit "1", el bit" 0 "y el bit" 1", de modo que el archivo será de 3 bits.

¿Es posible? Busqué en la web y traté de hacer esto:

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

Pero al final, cuando verifico los bytes de los archivos, Windows me dice que es un archivo 4bytes! Y no 3bits!

¿Cómo puedo hacer esto, si es posible? Muchas gracias.

Author: Francesco Bonizzi, 2012-11-06

5 answers

Todos los sistemas de files1 tratan con archivos en términos de bytes (y asignan espacio de almacenamiento con una granularidad mucho mayor, 512 bytes al mínimo). No hay manera de que usted va a obtener un archivo que es 3 bits de largo.

Lo mejor que puedes hacer es usar un byte entero pero ignorar 5 de sus bits. Para hacer eso (suponiendo que el número siempre va a caber en un byte), convierta la cadena de entrada a un tipo integral:

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

Entonces obtener su menos significativo byte:

unsigned char b = l & 0xffl;

Y escribirlo en el archivo:

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

1 Bueno, tal vez no todos. Podría haber algunos investigadores en algún lugar que experimentan con sistemas de archivos de tamaño de bits. No lo sabría.

 31
Author: Jon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-11-06 14:14:14

Su archivo de salida tiene 4 bytes de longitud porque está escribiendo un int en el archivo. En la mayoría de las plataformas, un int es de 4 bytes de tamaño.

No podrá escribir menos de 1 byte a la vez.

 14
Author: jbowes,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-11-06 14:07:52

Lo que puedes hacer es escribirlo como bits (3) y llenarlo hasta un byte con 0. Sin embargo, también necesita comenzar (o terminar) con el número de bits (o bits del último byte) que realmente se utilizan.

Por ejemplo (usando el primer byte como longitud):

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

En este caso, la sobrecarga del primer byte (longitud) es del 50%, cuanto más larga sea la cadena, menor será el porcentaje de sobrecarga, por supuesto.

 6
Author: Michel Keijzers,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-11-06 14:16:46

2 notas sobre su enfoque:

  1. Las computadoras[modernas] no pueden manejar menos de 1 byte en memoria, por lo que no podrá escribir bits individuales en el disco.

    Además, los sistemas de archivos suelen asignar espacio en trozos (512 bytes, 1Kb, ...) donde encaja el archivo. Por lo tanto, si tiene un archivo de 500 bytes, en realidad está perdiendo 512 bytes de espacio en disco.

  2. atoi() no convierte de cadena a números binarios, sino a enteros. En realidad estás escribiendo 0b1100101, que es 0d101. Deberías hacer la conversión primero. Algo como:

    char b = 0;
    for (int i=0; c[i]!=NULL; i++) 
    {
        b = ((b<<1) | atoi(c[i]));
    }
    
 5
Author: J.A.I.L.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-11-06 14:48:09

No estás escribiendo los bits 101, sino el valor binario del número decimal 101, es decir 1100101. Debido a que tiene fread un tamaño de sizeof(x) bytes, su archivo tendrá sizeof(x) bytes de longitud.

 3
Author: md5,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-11-06 14:11:13