C leer el código binario

Estoy tratando de construir un simulador de canalización de instrucciones y estoy teniendo muchos problemas para comenzar. Lo que tengo que hacer es leer binario de stdin, y luego almacenarlo en memoria de alguna manera mientras manipulo los datos. Necesito leer en pedazos de exactamente 32 bits uno después del otro.

¿Cómo leo en pedazos de exactamente 32 bits a la vez? En segundo lugar, ¿cómo lo almaceno para la manipulación más adelante?

Esto es lo que tengo hasta ahora, pero al examinar los fragmentos binarios que leo más adelante, simplemente no se ve bien, no creo que esté leyendo exactamente 32 bits como los necesito.

char buffer[4] = { 0 }; // initialize to 0 unsigned long c = 0; int bytesize = 4; // read in 32 bits while (fgets(buffer, bytesize, stdin)) { memcpy(&c, buffer, bytesize); // copy the data to a more usable structure for bit manipulation later // more stuff buffer[0] = 0; buffer[1] = 0; buffer[2] = 0; buffer[3] = 0; // set to zero before next loop } fclose(stdin); 

¿Cómo leo en 32 bits a la vez (son todos 1/0, sin líneas nuevas, etc.) y en qué lo guardo? ¿Está bien char[] ?

EDITAR: puedo leer el binario, pero ninguna de las respuestas produce los bits en el orden correcto: todos están destrozados, sospecho endianidad y problemas para leer y mover 8 bits (1 char) a la vez, esto necesita trabajar en Windows y C …?

Lo que necesitas es freopen() . De la página de manual:

Si filename es un puntero nulo, la función freopen () intentará cambiar el modo de la secuencia a la especificada por modo, como si se hubiera usado el nombre del archivo actualmente asociado con la secuencia. En este caso, el descriptor de archivo asociado con la secuencia no necesita cerrarse si la llamada a freopen () tiene éxito. Está definido por la implementación qué cambios de modo son permitidos (si hay alguno) y en qué circunstancias.

Básicamente, lo mejor que puedes hacer es esto:

 freopen(NULL, "rb", stdin); 

Esto volverá a abrir stdin para ser el mismo flujo de entrada, pero en modo binario. En el modo normal, la lectura de stdin en Windows convertirá \r\n (nueva línea de Windows) al carácter único ASCII 10. Al usar el modo "rb" , se deshabilita esta conversión para que pueda leer correctamente en los datos binarios.

freopen() devuelve un freopen() , pero es el valor anterior (antes de ponerlo en modo binario), así que no lo use para nada. Después de eso, use fread() como se ha mencionado.

En cuanto a sus inquietudes, sin embargo, es posible que no esté leyendo en “32 bits”, pero si usa fread() , estará leyendo en 4 char (que es lo mejor que puede hacer en C, se garantiza que el carácter del tema será al menos 8 bits, pero algunas plataformas históricas e incrustadas tienen caracteres de 16 bit (algunos incluso tienen 18 o peor)). Si usa fgets() , nunca leerá en 4 bytes. Leerá al menos 3 (dependiendo de si alguno de ellos son líneas nuevas), y el 4to byte será '\0' porque las cadenas C terminan en fgets() y fgets() termina nul-termina lo que lee (como una buena función ) Obviamente, esto no es lo que quieres, entonces deberías usar fread() .

Considere usar SET_BINARY_MODE macro y setmode :

 #ifdef _WIN32 # include  # include  # define SET_BINARY_MODE(handle) setmode(handle, O_BINARY) #else # define SET_BINARY_MODE(handle) ((void)0) #endif 

Más detalles sobre la macro SET_BINARY_MODE aquí: ” Manejo de archivos binarios mediante E / S estándar ”

Más detalles sobre el modo de setmode aquí: “_setmode ”

fgets () está todo mal aquí. Está dirigido a texto ASCII legible por humanos terminado por caracteres de final de línea, no datos binarios, y no le proporcionará lo que necesita.

Hace poco hice exactamente lo que quería con la llamada de lectura () . A menos que su progtwig haya cerrado explícitamente stdin, para el primer argumento (el descriptor de archivo), puede usar un valor constante de 0 para stdin. O bien, si tiene un sistema POSIX (Linux, Mac OS X o alguna otra variante moderna de Unix), puede usar STDIN_FILENO.

No sé qué SO estás ejecutando, pero normalmente no puedes “abrir stdin en binario”. Puedes probar cosas como

 int fd = fdreopen (fileno (stdin), outfname, O_RDONLY | OPEN_O_BINARY); 

para tratar de forzarlo. Entonces usa

 uint32_t opcode; read(fd, &opcode, sizeof (opcode)); 

Pero realmente no lo he probado yo mismo. 🙂

Tuve que completar la respuesta a partir de los diversos comentarios de las personas amables de arriba, así que aquí hay una muestra totalmente funcional que funciona, solo para Windows, pero probablemente pueda traducir las cosas específicas de Windows a su plataforma.

 #include "stdafx.h" #include "stdio.h" #include "stdlib.h" #include "windows.h" #include  #include  int main() { char rbuf[4096]; char *deffile = "c:\\temp\\outvideo.bin"; size_t r; char *outfilename = deffile; FILE *newin; freopen(NULL, "rb", stdin); _setmode(_fileno(stdin), _O_BINARY); FILE *f = fopen(outfilename, "w+b"); if (f == NULL) { printf("unable to open %s\n", outfilename); exit(1); } for (;; ) { r = fread(rbuf, 1, sizeof(rbuf), stdin); if (r > 0) { size_t w; for (size_t nleft = r; nleft > 0; ) { w = fwrite(rbuf, 1, nleft, f); if (w == 0) { printf("error: unable to write %d bytes to %s\n", nleft, outfilename); exit(1); } nleft -= w; fflush(f); } } else { Sleep(10); // wait for more input, but not in a tight loop } } return 0; } 

fread () se adapta mejor para leer datos binarios.

Sí, char array está bien, si está planeando procesarlos bytewise.

Lo hice bien la primera vez, excepto que necesitaba ntohl … Conversión de C Endian: poco a poco