2017-09-27 7 views
1

Je dispose d'un fichier de key.hex qui contient:Lecture des valeurs hexadécimaux de fichiers et de les afficher en C

00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 

en tant que valeurs hexadécimaux. J'essaie de les lire et de les imprimer immédiatement:

unsigned char key[16]; 
FILE *secretkey; 
secretkey = fopen("key.hex", "r+"); 
fgets(key, 16, secretkey); 
int j = 0; 
for(j = 0; j < sizeof(key) ; j++) { 
    printf("%02x ", key[j]); 
} 

Cependant, comme je l'ai la sortie suivante:

00 01 02 03 04 05 06 07 08 09 0a 00 80 d2 73 b7 

Pourquoi la sortie ne correspond pas au contenu du fichier?

+1

Vous avez lu 15 *** caractères *** dans 'key', pas la ligne complète, et vous l'avez lu comme une chaîne *** *** pas comme des entiers séparés. –

+4

Dans un environnement ASCII typique '0a' est un saut de ligne (' LF' ou '\ n'), qui termine votre appel' fgets', donc vous ne lisez pas les octets restants. Utilisez 'fread' au lieu de' fgets'. –

+4

Ces numéros sont-ils stockés sous forme de texte ou de valeurs binaires? – Gerhardh

Répondre

2

Paul R .:
Dans un environnement ASCII typique est 0a saut de ligne (LF ou \n), qui met fin à votre fgets appel, de sorte que vous ne lisez pas les octets restants.
Utilisez fread au lieu de fgets.

E.g.
(lignes les plus pertinentes à partir du code liées au commentaire par BLUEPIXY, qui est un démonstrateur complet):.

secretkey = fopen("key.hex", "r+b"); 
fread(key, 1, sizeof key, secretkey); 

(Cette compile une réponse de deux commentaires, chacun serait une réponse décente Je vous offre . supprimer si l'un des deux auteurs fait leur propre réponse et me demande de)

1

Vous avez dit que le fichier contient ces valeurs hexadécimaux:

00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 

Ainsi, le f ile contient précisément 16 octets: la première a une valeur 0x00, la seconde a valeur 0x01, etc.

C'est ce qu'on appelle un fichier binaire . Ce n'est vraiment pas un fichier texte. Il n'y a presque pas de caractères ordinaires et imprimables dans ce fichier. Si nous devions imprimer ce fichier à l'écran, nous verrions des glyphes étranges et des déchets, ou peut-être rien.

Mais la fonction fgets est destinée à lire une ligne de texte à partir d'un fichier texte. Plus précisément, il lit les caractères jusqu'à et y compris l'indication de fin de ligne. Sur les systèmes Unix/Linux, l'indication de fin de ligne est le caractère de saut de ligne. En ASCII, le caractère de saut de ligne a le code de caractère 0x0a. En outre, puisque la fonction fgets est destinée à fonctionner avec du texte, elle convertit le texte qu'elle lit en une chaîne C, en ajoutant un octet nul (0x00 ou '\0') à la fin du tampon de sortie.

Qu'est-il arrivé est que fgets lu que les 11 premiers caractères du fichier, jusqu'à et y compris la 0A, et écrit ces caractères ainsi que le caractère nul final au tableau key. Il n'a donc rempli que les 12 premières cellules du tableau. Les 4 derniers caractères ont conservé les valeurs de poubelle non initialisées que contenait le tableau lorsque vous l'avez défini pour la première fois. (Dans ce cas, on dirait qu'ils étaient 80, d2, 73 et b7.)

Mais ce que vous voulez vraiment faire dans ce cas, il semble que, est lu 16 octets bruts, sans supposer qu'ils » re text, sans chercher de retour à la ligne, sans mettre fin au résultat.C'est une exigence très différente, mais il s'avère qu'il existe une autre fonction de bibliothèque standard qui fait exactement ce que vous voulez: fread.

donc récrire votre code comme ceci:

FILE *secretkey; 
secretkey = fopen("key.hex", "rb"); 
if(secretkey == NULL) { 
    fprintf(stderr, "can't open %s\n", "key.hex"); 
    exit(1); 
} 
int r = fread(key, 1, 16, secretkey); 
if(r != 16) { 
    fprintf(stderr, "error reading key: read %d chars, expected %d\n", r, 16); 
    exit(1); 
} 
int j; 
for(j = 0; j < sizeof(key) ; j++) { 
    printf("%02x ", key[j]); 
} 

Vous remarquerez que j'ai également ajouté le code pour vérifier que fread ont lu en fait 16 octets comme prévu. J'ai également ajouté du code pour vérifier que l'appel fopen a réussi à ouvrir le fichier "key.hex". J'ai également changé l'appel fopen pour ouvrir le fichier en mode binaire ("rb"), et supprimer le modificateur +, que vous ne voulez probablement pas.

Comme une note de côté, si vous voulez faire une meilleure gestion des erreurs, lors de l'ouverture d'un fichier échoue, il est toujours une bonne idée d'imprimer un message d'erreur plus descriptif indiquant pourquoi le fichier n'a pas pu être ouvert:

if(secretkey == NULL) { 
    fprintf(stderr, "can't open %s: %s\n", "key.hex", strerror(errno)); 
    exit(1); 
} 

pour ce faire, vous devrez également inclure les fichiers d'en-tête <string.h> pour la fonction strerror() et <errno.h> pour la valeur errno.