web-dev-qa-db-fra.com

Lecture d'un fichier binaire 1 octet à la fois

J'essaie de lire un fichier binaire à la fois dans un octet C 1 et après des heures de recherche sur Internet, je ne parviens toujours pas à le faire récupérer autre chose que des ordures et/ou une erreur distincte. Fondamentalement, le fichier binaire est au format d’une liste de 256 éléments et chaque élément d’un octet (un unsigned int compris entre 0 et 255). J'essaie d'utiliser fseek et fread pour accéder à "l'index" du fichier binaire et récupérer cette valeur. Le code que j'ai actuellement:

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

En ce moment, ce code me donne des numéros de poubelle aléatoires et des erreurs de segmentation. Des conseils sur la manière dont je peux obtenir que cela fonctionne correctement?

18
RogerB

Dans votre code, vous essayez de lire 256 octets à l'adresse d'un int. Si vous voulez lire un octet à la fois, appelez fread(&buffer, 1, 1, file); (voir fread ).

Mais une solution plus simple consiste à déclarer un tableau d'octets, à le lire en entier et à le traiter par la suite.

16
MByD

Vos octets déroutants avec int . Le terme commun pour un octet est un unsigned char . La plupart des octets ont une largeur de 8 bits. Si les données que vous lisez sont 8 bits, vous devrez lire 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 raison pour la lecture de toutes les données en mémoire est de garder les E/S en mouvement. Un surcoût est associé à chaque demande d'entrée, quelle que soit la quantité demandée. Lire un octet à la fois ou chercher une position à la fois est le pire des cas. 

Voici un exemple de la surcharge nécessaire à la lecture d'un octet:

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.

Dans la conception de votre programme, les étapes ci-dessus seront répétées 256 fois. Avec la suggestion de tout le monde, la ligne marquée de "->" indiquera 256 octets. Ainsi, la surcharge est exécutée une seule fois au lieu de 256 fois pour obtenir la même quantité de données.

14
Thomas Matthews
unsigned char buffer; // note: 1 byte
fread(&buffer, 1, 1, file);

Il est temps de lire les mans je crois. 

3
c-smile

Vous essayez de lire 256 octets dans une variable entière de 4 octets appelée "tampon". Vous écrasez les 252 octets suivants d’autres données.

Il semble que buffer devrait être soit unsigned char buffer[256];, soit vous devriez utiliser fread(&buffer, 1, 1, f) et dans ce cas, buffer devrait être unsigned char buffer;

Si vous ne voulez qu'un seul caractère, vous pouvez simplement laisser buffer en tant que int ( unsigned n'est pas nécessaire, car C99 garantit une plage minimale raisonnable pour plain int) et simplement dire:

buffer = fgetc(f);
1
DigitalRoss

Quelques problèmes avec le code tel quel.

Le prototype de fread est:

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

Vous avez défini la taille à 256 (octets) et le nombre à 1. C'est bien, cela signifie "lire un morceau de 256 octets, le placer dans le tampon".

Cependant, votre mémoire tampon a une longueur de l'ordre de 2 à 8 octets (ou du moins, beaucoup moins que 256 octets), vous avez donc un dépassement de mémoire tampon. Vous voudrez probablement utiliser fred (& buffer, 1, 1, file).

De plus, vous écrivez des données d'octets sur un pointeur int. Cela fonctionnera sur une finalité (petit-endian, en fait), de sorte que tout ira bien pour l'architecture Intel et apprendra de mauvaises habitudes qui vont revenir et vous mordre, un de ces jours.

Essayez très fort d'écrire uniquement des données d'octet dans un stockage organisé par octet, plutôt que dans des entiers ou des flottants.

0
Vatine