2011-05-23 11 views
16

Estoy tratando de leer un archivo binario en C 1 byte a la vez y después de buscar en Internet durante horas, todavía no puedo obtenerlo para recuperar nada más que basura y/o seg culpa. Básicamente, el archivo binario está en el formato de una lista que tiene 256 elementos de longitud y cada elemento es de 1 byte (un int sin signo entre 0 y 255). Estoy tratando de usar fseek y fread para saltar al "índice" dentro del archivo binario y recuperar ese valor. El código que tengo actualmente:Leyendo un archivo binario 1 byte a la vez

unsigned int buffer; 

int index = 3; // any index value 

size_t indexOffset = 256 * index; 
fseek(file, indexOffset, SEEK_SET); 
fread(&buffer, 256, 1, file); 

printf("%d\n", buffer); 

Ahora este código me está dando números aleatorios de basura y fallas seg. Algún consejo sobre cómo puedo hacer que esto funcione, ¿verdad?

+5

Leer un archivo de un byte a la vez supondría una sobrecarga de E/S masiva. Un mejor enfoque sería leer todo el archivo en un búfer (ya que solo tiene 256 bytes) y procesar cada byte almacenado en el búfer de forma individual. – titaniumdecoy

+0

¿Por qué no utilizar fgetc – Dirk

+2

@titaniumdecoy? Creo que el Administrador de E/S almacenará en búfer las lecturas en los sistemas operativos modernos. – jww

Respuesta

16

En su código está tratando de leer 256 bytes a la dirección de uno int. Si desea leer un byte a la vez, llame al fread(&buffer, 1, 1, file); (consulte fread).

Pero una solución más simple será declarar una matriz de bytes, leerla todos juntos y procesarla después de eso.

+1

el búfer es del tipo unsigned int. No inicializado y, por lo tanto, después de su 'fread (& buffer, 1, 1, file);' obtendrá un número donde 24 bits contendrán algún valor aleatorio. –

+0

Eso es verdad. Gracias. – MByD

+0

¿Cómo declaras un conjunto de bytes y lo lees todo junto? ¡Gracias! –

3
unsigned char buffer; // note: 1 byte 
fread(&buffer, 1, 1, file); 

Es hora de leer sirve, creo.

1

Está tratando de leer 256 bytes en una variable entera de 4 bytes llamada "buffer". Está sobrescribiendo los próximos 252 bytes de otros datos.

Parece que buffer o bien debe ser unsigned char buffer[256]; o que debería estar haciendo fread(&buffer, 1, 1, f) y en ese caso debe ser bufferunsigned char buffer;.

otra parte, si lo que desea es un solo carácter, se puede simplemente dejar buffer como int (sin firmar no es necesaria debido a C99 garantiza un alcance mínimo razonable para int normal) y simplemente decir:

buffer = fgetc(f); 
0

Un par de problemas con el código tal como está.

El prototipo para fread es:

size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream); 

que haya establecido el tamaño a 256 (bytes) y el recuento a 1. Eso está bien, que significa "leer un trozo de 256 bytes, empujar hacia el buffer ".

Sin embargo, su búfer es del orden de 2-8 bytes de longitud (o, al menos, mucho más pequeño que 256 bytes), por lo que tiene un desbordamiento de búfer. Probablemente desee utilizar fred (& buffer, 1, 1, file).

Además, está escribiendo datos de bytes en un puntero int. Esto funcionará en un extremo (de hecho, pequeño endian), así que estarás bien en la arquitectura Intel y de eso aprenderás los malos hábitos que volverán y te morderán, uno de estos días.

Intente realmente escribir datos de bytes en el almacenamiento organizado por byte, en lugar de en ints o flotantes.

+1

¿Por qué su prototipo para 'fread' contiene' fwrite'? –

+0

Error de cortar y pegar. Gracias, arreglado. – Vatine

14

Su confuso bytes con int. El término común para byte es unsigned char. La mayoría de los bytes tienen 8 bits de ancho.Si los datos que está leyendo es de 8 bits, tendrá que leer en 8 bits:

#define BUFFER_SIZE 256 

unsigned char buffer[BUFFER_SIZE]; 

/* Read in 256 8-bit numbers into the buffer */ 
size_t bytes_read = 0; 
bytes_read = fread(buffer, sizeof(unsigned char), BUFFER_SIZE, file_ptr); 
// Note: sizeof(unsigned char) is for emphasis 

La razón para la lectura de todos los datos en la memoria es mantener la E/S que fluye. Hay una sobrecarga asociada con cada solicitud de entrada, independientemente de la cantidad solicitada. Leer un byte a la vez, o buscar una posición a la vez es el peor de los casos.

Aquí se muestra un ejemplo de la sobrecarga necesaria para la lectura de 1 byte:

Tell OS to read from the file. 
OS searches to find the file location. 
OS tells disk drive to power up. 
OS waits for disk drive to get up to speed. 
OS tells disk drive to position to the correct track and sector. 
-->OS tells disk to read one byte and put into drive buffer. 
OS fetches data from drive buffer. 
Disk spins down to a stop. 
OS returns 1 byte to your program. 

En el diseño del programa, los pasos anteriores se repetirán 256 veces. Con la sugerencia de todos, la línea marcada con "->" leerá 256 bytes. Por lo tanto, la sobrecarga se ejecuta solo una vez en lugar de 256 veces para obtener la misma cantidad de datos.

+2

Buena dramatización. – ybakos

+0

Me han dicho que el sistema operativo realmente almacena en búfer. De todos modos, si no es así, estoy bastante seguro de que el controlador de disco hace un poco de almacenamiento en búfer. – Nolan

+0

Sí, pero siempre hay instrucciones generales para llamar a la función de entrada; tal vez incluyendo la recarga de la memoria caché de instrucciones. Para aumentar el rendimiento, esta sobrecarga debe reducirse, por lo tanto, más datos por solicitud es más eficiente. –

Cuestiones relacionadas