Bonjour,
je souhaite lire des mots de 16 bits dans un fichier afin de le convertir ensuite en un entier.
Comment procéder pour lire ces bits ?
Bonjour,
je souhaite lire des mots de 16 bits dans un fichier afin de le convertir ensuite en un entier.
Comment procéder pour lire ces bits ?
Attention évidemment aux problèmes d'endianness.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4 if (1 != fread(buf, 2, 1, file)) { perror("fread"); ... }
Bonjour,
Il faut d'abord savoir si les mots sont stockés sous forme de texte ou binaire.
Texte :Binaire :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14 /* définition d'un entier court, de taille 16 bits sur x86 (cf FAQ pour plus de précisions) */ short int i; int ret; /* ouverture en mode texte */ FILE * f = fopen("mon_fichier", "r"); if(NULL == f) { /* gestion de l'erreur d'ouverture */ } else { ret = fscanf(f, "%hd", &i); if(1 != ret) { /* gestion de l'erreur de lecture */ } }
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13 /* définition d'un entier court */ short int i; int ret; /* ouverture en mode lecture binaire */ FILE * f = fopen("mon_fichier", "rb"); if(NULL == f) { /* gestion de l'erreur d'ouverture */ } else { ret = fread(&i, sizeof(i), 1, f); if(1 != ret) { /* gestion de l'erreur de lecture */ } }
Merci pour vos réponses.
En fait je souhaite lire un fichier quelconque afin de le crypter (je souhaite donc faire des opérations sur les bits). Une lecture binaire est donc nécessaire non ?
J'aurais aussi une autre question :
comment faire pour des mots plus grands (eg. 512 bits) ?
Pas de Wi-Fi à la maison : CPL
pour lire des champs de bit si tu sais par exemple qu'il y a dans ton fichier un nombre entier sur 4 octets suivit par exemple d'un nombre entier sur 2 octets puis pour finir une chaine de caractere de 5 caracteres chacuns sur 1 octets tu peux faire des lectures de structures directement en faisant :
attention quand meme selon l'architecture ou tu te trouves, les tailles des types peuvent varié, ceci n'est qu'un exemple dans le cas general.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7 typedef struct myread { int first; short second; char third[5]; } __attribute__ ((packed)) myread;
ensuite tu peux "lire" directement ta structure dans ton fichier si les bits sont cote à cote sans separateur evidement.
exemple :
tu peux aussi si par exemple tu veux lire 8 bits cote à cote separement
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13 myread test; /* définition d'un entier court */ int ret; /* ouverture en mode lecture binaire */ FILE * f = fopen("mon_fichier", "rb"); if(NULL == f) { /* gestion de l'erreur d'ouverture */ } else { ret = fread(&test, sizeof(test), 1, f); //d'hab pour faire ca j'utilise des appels plus bas niveau open et read, je prefere controler au plus pret ce que fais la machine, mais je pense que ca fonctionne pareil avec fopen et fread if(1 != ret) { /* gestion de l'erreur de lecture */ }
utilisé ce que l'on appel des bitfields
le ': x' specifie au compilateur que tu ne veux utiliser que x bit sur le type definit. le packed te permet d'etre sur qu'il n'y aura pas entre les champs de bits tampons etc.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12 struct a_byte { unsigned int bit0:1; unsigned int bit1:1; unsigned int bit2:1; unsigned int bit3:1; unsigned int bit4:1; unsigned int bit5:1; unsigned int bit6:1; unsigned int bit7:1; } __attribute__((packed));
Attention au probleme d'allignement avec ce genre d'astuce sur certaine architecture par contre.
si tu veux plus d'informations regarde du coté des attributes possible et leur utilités, et les bitfields. Je ne garantie pas la compilation de ces codes, je les ai ecris "on the fly", je n'ai pas de compilateur C sous la main actuellement pour tester. Ce n'est cas titre d'information
Pas de Wi-Fi à la maison : CPL
certe je l'ai bien precisé dans mon message, mais je trouve cela bien utile quand meme si le code n'a pas besoin d'etre portable sur toutes les architectures. De plus il y a moyen de rendre cela portable. Ceci n'est qu'un exemple.
Pas de Wi-Fi à la maison : CPL
dans ce cas la, c'est la lecture de bit en general qui est infernal et non portable, car que l'on utilise un champ de bit ou un short de 2 octets comme vous faites au dessus n'est pas portable non plus, dans un cas le masque pour le short sera par exemple 0xFF00 et dans un autre 0x00FF si l'on est en little ou big endian.
Ceci n'est en rien une aggression, plutot une curiosité de ma part, car j'en viens à me poser la question aussi.
est ce que le 1er code (qui a mes yeux mise à part le coté portabilité est plus du bricolage) est portable ? si l'on change d'archi, donc de taille de type, donc d'endianness aussi imaginons ?
Vu sa question, j'ai l'impression que ce qui l'intéresse est la lecture de mots et pas leur interprétation. Quand il demande à lire 2 octets, il ne se soucie pas de savoir s'il s'agit d'un short (...) mais il veut seulement 2 octets. D'où le fread 'brut' avec le nombre d'octets voulus. Par contre avec une structure ou un champs de bit, là tu interprète ce que tu lis. D'où risque!
Ressources proposées par 3DArchi - Les fonctions virtuelles en C++ - Cours et tutoriels C++ - FAQ C++ - Forum C++.
Pour être portable, il faut définir un format de flux (fichier, réseau) indépendant de l'architecture.
Une manière simple est de définir le format de flux selon la norme 'réseau', c'est à dire "MSB en tête" :
ensuite pour écrire dans le flux, on fait :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5 Entier de 16-bit : [0] octet MSB [1] octet LSB
a la lecture, on fait le contraire :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5 unsigned data = 0x1234; fputc ((data >> (8 * 1), fp); /* MSB : 0x12 */ fputc ((data >> (8 * 0), fp); /* LSB : 0x34 */
En fait, c'est un peu plus compliqué, car il faut surveiller EOF, mais le principe est là... On peut aussi passer par un tableau de unsigned char que l'on ecrit / lit à la main et utiliser fwrite() / fread()...
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5 unsigned data = 0; data |= (fgetc (fp) << (8 * 1)); /* MSB : 0x1200 */ data |= (fgetc (fp) << (8 * 0)); /* LSB : 0x1234 */
La version 32-bit :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7 Entier de 32-bit : [0] octet MSB [1] octet [2] octet [3] octet LSB
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7 unsigned long data = 0x12345678; fputc ((data >> (8 * 3), fp); /* MSB : 0x12 */ fputc ((data >> (8 * 2), fp); /* : 0x34 */ fputc ((data >> (8 * 1), fp); /* : 0x56 */ fputc ((data >> (8 * 0), fp); /* LSB : 0x78 */
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7 unsigned long data = 0; data |= (fgetc (fp) << (8 * 3)); /* MSB : 0x12000000 */ data |= (fgetc (fp) << (8 * 2)); /* : 0x12340000 */ data |= (fgetc (fp) << (8 * 1)); /* : 0x12345600 */ data |= (fgetc (fp) << (8 * 0)); /* LSB : 0x12345678 */
Pas de Wi-Fi à la maison : CPL
Vous avez un bloqueur de publicités installé.
Le Club Developpez.com n'affiche que des publicités IT, discrètes et non intrusives.
Afin que nous puissions continuer à vous fournir gratuitement du contenu de qualité, merci de nous soutenir en désactivant votre bloqueur de publicités sur Developpez.com.
Partager