IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C Discussion :

Comment décoder un fichier binaire ?


Sujet :

C

  1. #1
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    44
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2007
    Messages : 44
    Points : 38
    Points
    38
    Par défaut Comment décoder un fichier binaire ?
    Bonjour,

    je dois lire un fichier binaire qui contient des blocs et récupérer les octets 9 à 16. Dans ces 8 octets figure la taille du fichier (qui peut donc être importante).
    Malheureusement je ne sais pas comment faire!

    Je peux bêtement lire les octets par fread et ensuite calculer la taille mais même en déclarant cette variable en long long int, j'ai le message d'erreur "attention : débordement d'entier dans l'expression"

    Mon code :

    taille=(int)c16+256*(int)c15+256*256*(int)c14+256*256*256*(int)c13+256*256*256*256*(int)c12+256*256*256*256*256*(int)c11+256*256*256*256*256*256*(int)c10+256*256*256*256*256*256*256*(int)c9;

    c9 représente l'octet 9, etc. jusqu'à c16.

    Je pense qu'il faut que je fasse un malloc parce que là je dois vous faire peur!

    Merci pour votre aide,

  2. #2
    Expert éminent Avatar de BufferBob
    Profil pro
    responsable R&D vidage de truites
    Inscrit en
    Novembre 2010
    Messages
    3 035
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : responsable R&D vidage de truites

    Informations forums :
    Inscription : Novembre 2010
    Messages : 3 035
    Points : 8 400
    Points
    8 400
    Par défaut
    salut,

    il faut connaitre le format de ton fichier, le plus efficace sera de passer par une (ou plusieurs) structure(s) et de fread la (ou les) structure(s) directement dans le fichier, préalablement ouvert avec l'attribut b pour binary

    hésite pas à fournir un code et/ou un morceau du fichier, son format etc. si besoin

  3. #3
    Nouveau membre du Club
    Inscrit en
    Juin 2013
    Messages
    18
    Détails du profil
    Informations forums :
    Inscription : Juin 2013
    Messages : 18
    Points : 35
    Points
    35
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    #include <fcntl.h>
     
    int handle;
    __int64 taille;
     
    handle = open ( "c:\\repertoire\\fichier" , O_RDONLY|O_BINARY );
    lseek ( handle , 9 , SEEK_SET );
    read ( handle , &taille , 8);
    close ( handle );
    Bonjour,

    voici un petit exemple
    l'entier "taille" est de type __int64 sinon tu ne pourra pas stocker 8 octets

    open : ouvre le fichier
    lseek se positionne su l'octet 9
    read lit 8 octets à partir de l'octet courrant (donc le 9ème : xe sont les octets de 9 à 16
    close ferme le fichier
    @+

  4. #4
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    44
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2007
    Messages : 44
    Points : 38
    Points
    38
    Par défaut
    Mon compilateur (gcc) ne reconnaît pas le type __int64.
    Comment je peux faire?

  5. #5
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    44
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2007
    Messages : 44
    Points : 38
    Points
    38
    Par défaut
    Je crois qu'il faut utiliser le type uint64_t en fait

  6. #6
    Nouveau membre du Club
    Inscrit en
    Juin 2013
    Messages
    18
    Détails du profil
    Informations forums :
    Inscription : Juin 2013
    Messages : 18
    Points : 35
    Points
    35
    Par défaut
    Citation Envoyé par yoyostras Voir le message
    Mon compilateur (gcc) ne reconnaît pas le type __int64.
    Comment je peux faire?
    essaie :
    long long taille;

  7. #7
    Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Juillet 2008
    Messages
    28
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juillet 2008
    Messages : 28
    Points : 62
    Points
    62
    Par défaut
    Bonjour à tous,

    tinofutinofu, si tu veux quelque chose de portable, il faudra passer par fopen : open est spécifique aux systèmes conformes POSIX (appel système) et sous Windows, un équivalent (avec des descripteurs) a été fait mais porte un nom légèrement différent... J'aurais aussi utilisé sizeof pour plus de clarté.

    EDIT : ça semble marcher avec le compilateur de Microsoft (pas de machine Windows sous la main pour l'instant) mais des warnings sont émis et il faut inclure io.h...

  8. #8
    Expert éminent Avatar de BufferBob
    Profil pro
    responsable R&D vidage de truites
    Inscrit en
    Novembre 2010
    Messages
    3 035
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : responsable R&D vidage de truites

    Informations forums :
    Inscription : Novembre 2010
    Messages : 3 035
    Points : 8 400
    Points
    8 400
    Par défaut
    @yoyostras: c'est quoi ton fichier binaire, un bmp ? un jpeg ? un wav ? autre ?

  9. #9
    Membre averti
    Avatar de ChipsAlaMenthe
    Homme Profil pro
    Ingénieur en eau chaude et ballon rond
    Inscrit en
    Mai 2015
    Messages
    138
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : Ingénieur en eau chaude et ballon rond
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : Mai 2015
    Messages : 138
    Points : 394
    Points
    394
    Par défaut
    Si le int64 ne marche pas, au pire essai de faire une structure avec deux int (de 32).
    Utilise ensuite les opérateurs de décalages binaires afin de pouvoir utiliser deux int32 comme un int 64. ^^

  10. #10
    Membre émérite
    Avatar de imperio
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2010
    Messages
    852
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2010
    Messages : 852
    Points : 2 298
    Points
    2 298
    Par défaut
    @ChipsAlaMenthe: Pourquoi faire simple et efficace quand on peut faire compliqué et dégueulasse, c'est bien ça ? Si des types ont été inventés, c'est bien pour une raison !

  11. #11
    Membre averti
    Avatar de ChipsAlaMenthe
    Homme Profil pro
    Ingénieur en eau chaude et ballon rond
    Inscrit en
    Mai 2015
    Messages
    138
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : Ingénieur en eau chaude et ballon rond
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : Mai 2015
    Messages : 138
    Points : 394
    Points
    394
    Par défaut
    @imperio
    Citation Envoyé par imperio Voir le message
    @ChipsAlaMenthe: Pourquoi faire simple et efficace quand on peut faire compliqué et dégueulasse, c'est bien ça ? Si des types ont été inventés, c'est bien pour une raison !
    Tu as des systèmes uniquement en 32 bits et dont les uint64 n'existent pas.
    Donc d'après le message:

    Mon compilateur (gcc) ne reconnaît pas le type __int64.
    Comment je peux faire?
    Etant donné que le type int64 n'est pas certain d'exister ici, j'imagine qu'une alternative est toujours intéressante dans l'hypothèse où le int64 n'existe pas. Sachant qu'on n'a pas la confirmation pour l'existence d'un uint64 après le message suivant:

    Je crois qu'il faut utiliser le type uint64_t en fait .
    Dans les systèmes embarqués tu n'as pas toujours le choix, tu dois parfois envoyer un nombre sur 16 bits sur un bus de 8 bits, et dans ce cas on fait passer par paquets. Etant donné qu'on ne sait pas sur quel système ça s'opère, il est toujours bon d'avoir une solution qui sera toujours meilleure à prendre qu'aucune solution .

  12. #12
    Expert éminent Avatar de BufferBob
    Profil pro
    responsable R&D vidage de truites
    Inscrit en
    Novembre 2010
    Messages
    3 035
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : responsable R&D vidage de truites

    Informations forums :
    Inscription : Novembre 2010
    Messages : 3 035
    Points : 8 400
    Points
    8 400
    Par défaut
    l'un dans l'autre, le posteur initial est jamais revenu, a jamais dit si il avait finalement trouvé la solution à son problème et à bien y regarder n'a même jamais eu trop l'air de lire ce qu'on disait, y'a sans doute pas lieu de se prendre la tête...

  13. #13
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Juin 2009
    Messages
    4 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 481
    Points : 13 679
    Points
    13 679
    Billets dans le blog
    1
    Par défaut
    Je suis d'accord avec le fait de préféré les fonctions préfixées par un f.

    Tu as des systèmes uniquement en 32 bits et dont les uint64 n'existent pas.
    Le type uint64_t est optionnel (voir la norme C99 à la section 7.18.1.1 Exact-width integer types, , mais pas que sur systèmes 32 bits. Et ce n'est par parce que tu es sur un système 32 bits que tu n'as pas un type qui contient au moins 64 bits. Voir la norme C99 à la section 7.18.1.2 Minimum-width integer types, point 3 :
    The follo
    wing types are required:
    int_least8_t
    int_least16_t
    int_least32_t
    int_least64_t
    uint_least8_t
    uint_least16_t
    uint_least32_t
    uint_least64_t
    All other types of this form are optional
    Si tu as besoin de 64 bits (non signé), tu peux utiliser uint_least64_t. Sur un système avec un bus 32 bits, on peut s'attendre à ce que le compilateur fasse lui-même les 2 accès sur le bus et la concaténation en assembleur. Ca peut arriver sur un compilateur non-conforme à la norme. Si on pense que ça a des grandes chances d'arriver, on peut déjà anticiper. Sinon, on utilise ce que fourni la norme pour plus de simplicité. Je me demande par contre dans le cas particulier du POsi on ne peut pas avoir un problème d'endianess...

    Dans les systèmes embarqués tu n'as pas toujours le choix, tu dois parfois envoyer un nombre sur 16 bits sur un bus de 8 bits, et dans ce cas on fait passer par paquets. Etant donné qu'on ne sait pas sur quel système ça s'opère, il est toujours bon d'avoir une solution qui sera toujours meilleure à prendre qu'aucune solution
    Il faut bien penser qu'il y a d'un côté le bus du CPU pour accéder aux mémoires, sur lequel l'assembleur généré à partir d'un code C peut faire lui même les différents accès si le bus est trop petit. C'est si on a un compilateur décent sur une architecture moderne en tout cas. J'ai fait un test pour Cortex-M3, une architecture 32 bits avec un langage assembleur assez lisible. Accessoirement, ce CPU a été pensé pour être programmable efficacement en C.

    Voici le code C qui nous intéresse :
    Voici l'assembleur généré (j'ai utilisé O1 pour avoir un truc qui me semble correct, en O0 je trouvais qu'il s'embêtait pour pas grand chose en passant tout sur la stack) :
    pgradot@pgradot-VirtualBox:~/Documents/C$ arm-none-eabi-gcc -O1 -c main.c -mthumb -mcpu=cortex-m3 && arm-none-eabi-objdump -d main.o 
    
    main.o:     file format elf32-littlearm
    
    
    Disassembly of section .text:
    
    00000000 <f_32>:
       0:	3001      	adds	r0, #1
       2:	4770      	bx	lr
    
    00000004 <f_64>:
       4:	3001      	adds	r0, #1
       6:	f141 0100 	adc.w	r1, r1, #0
       a:	4770      	bx	lr
    
    
    Sur Cortex-M, les paramètres sont passés de r0 à r3 et la valeur de retour est mise à partir de r0. Tous ces registres sont 32 bits.
    - On voit qu'avec un nombre 32 bits (exact) est passé dans r0 et qu'on ajoute simple 1 à r0. On retourne directement, la valeur résultante étant déjà dans le bon registre.
    - On voit qu'un nombre 64 bits au moins fait exactement 32 bits et est passé sur 2 registres, r0 et r1. L'assembleur ajoute 1 à la partie basse (on est en little endian) et 0 à la partie haute. On retourne ensuite directement, la valeur de retour étant déjà dans les bons registres.

    D'un autre côté les bus périphériques pour lesquelles tu fais souvent manuellement les passages par paquets. Si je souhaite écrire mes nombres sur une ligne série via une UART, le port UART du CPU fait 8 bits donc je suis obligé de découper d'envoyer moi-même byte par byte.

Discussions similaires

  1. Comment manipuler des fichiers binaires ?
    Par yrejk dans le forum C++
    Réponses: 1
    Dernier message: 15/04/2008, 19h40
  2. Réponses: 3
    Dernier message: 19/02/2007, 23h01
  3. Réponses: 2
    Dernier message: 20/11/2006, 18h37
  4. comment lire des fichiers binaires
    Par compton dans le forum Autres Logiciels
    Réponses: 8
    Dernier message: 06/07/2006, 12h03
  5. [Postgres]comment inserer des fichier binaires ?
    Par amin001 dans le forum PostgreSQL
    Réponses: 1
    Dernier message: 24/12/2005, 01h40

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo