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 :

Ecriture/Lecture Binaire (la suite)


Sujet :

C++

  1. #1
    Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2011
    Messages
    91
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Val de Marne (Île de France)

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

    Informations forums :
    Inscription : Décembre 2011
    Messages : 91
    Points : 48
    Points
    48
    Par défaut Ecriture/Lecture Binaire (la suite)
    Re bonsoir,

    J'ai honte de poster autant de question mais le binaire c'est clairement pas mon fort donc si je le fais pas et que je n'ai pas de coup de pouce je pense rester sur cette partie très longtemps alors je tente..

    Iradrille m'a passé ce jolie code qui me permet d'écrire dans l'endianess que je souhaite à peu près tout ce que je souhaite :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    #include <iostream>
    #include <fstream>
    #include <stdint.h>
     
    template <size_t> struct unsigned_ { };
    template <> struct unsigned_<1> { typedef uint8_t type; };
    template <> struct unsigned_<2> { typedef uint16_t type; };
    template <> struct unsigned_<4> { typedef uint32_t type; };
    template <> struct unsigned_<8> { typedef uint64_t type; };
     
    template <class T>
    void write(T val, std::ostream& os, bool big_endian=true)
    {
    	const size_t size = sizeof(T);
    	typedef unsigned_<size>::type type;
    	for(size_t i=0; i<size; ++i) {
    		type *ptr = reinterpret_cast<type*>(&val);
    		os << static_cast<unsigned char>(((*ptr) >> (big_endian ? size-i-1: i)*8));
    	}
    }
    Je l'ai quelque peu modifier pour que ça n'écrive pas directement dans le fichier mais plutôt en mémoire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    template <class T>
    void write(T val, char *data, bool big_endian=true)
    {
    	const size_t size = sizeof(T);
    	typedef unsigned_<size>::type type;
            type *ptr = reinterpret_cast<type*>(&val);
            unsigned char c[size];
    	for(size_t i=0; i<size; ++i) 
              c[i] << static_cast<unsigned char>(((*ptr) >> (big_endian ? size-i-1: i)*8));
    	memcpy(data, c, size);
    }
    //et plus loins je fais le write de data dans le fichier
    Maintenant dans data j'ai mes valeurs mais j'aimerai à présent faire la manipulation inverse, un read plus précisément.
    J'ai beau tourner le truc dans tous les sens impossible que ca compile ou que ca fonctionne:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    emplate <class T>
    void read(T *val, char *data, bool big_endian=true)
    {
    	const size_t size = sizeof(T);
    	typedef unsigned_<size>::type type;
            type *ptr = reinterpret_cast<type*>(&val);
            unsigned char c[size];
            memcpy(c, data, size); // Je prends la zone mémoire concernée
    	for(size_t i=0; i<size; ++i) 
              static_cast<unsigned char>(((*ptr) >> (big_endian ? size-i-1: i)*8)) = c[i]; // Ce que j'aurai voulu faire mais pas possible d'assigner à un cast
     
    }
    Merci encore pour votre aide.

  2. #2
    Expert confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2012
    Messages
    1 711
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2012
    Messages : 1 711
    Points : 4 442
    Points
    4 442
    Par défaut
    Hello,

    Tu peux t'en sortir en prenant T comme un unsigned char[] et en le remplissant dans le bon ordre.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    template <class T>
    void read(T& val, const unsigned char* data, bool big_endian=true) {
    	const size_t size = sizeof(T);
    	unsigned char *ptr = reinterpret_cast<unsigned char*>(&val);
    	for(size_t i=0; i<size; ++i) {
    		ptr[big_endian ? size-i-1: i] = data[i];
    	}
    }
     
    int main() {
    	const unsigned char data[] = { 0x00, 0x7f, 0x12, 0x01, 0x0a, 0x0b, 0x12, 0x34, 0x42, 0x28, 0x00, 0x00 };
    	uint16_t i16;
    	uint8_t i8;
    	float f;
     
    	read(i16, &data[0]);
    	std::cout << i16 << std::endl;
    	read(i8, &data[2]);
    	std::cout << (unsigned int)i8 << std::endl;
    	read(i8, &data[3]);
    	std::cout << (unsigned int)i8 << std::endl;
    	read(i8, &data[4]);
    	std::cout << (unsigned int)i8 << std::endl;
    	read(i8, &data[5]);
    	std::cout << (unsigned int)i8 << std::endl;
    	read(i16, &data[6]);
    	std::cout << i16 << std::endl;
    	read(f, &data[8]);
    	std::cout << f << std::endl;
     
    	return 0;
    }

  3. #3
    Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2011
    Messages
    91
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Val de Marne (Île de France)

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

    Informations forums :
    Inscription : Décembre 2011
    Messages : 91
    Points : 48
    Points
    48
    Par défaut
    Merci beaucoup ça fonctionne parfaitement.
    Et si maintenant l'étape d'après c'était non plus d'écrire ou de lire des octets mais plutôt des bits, serait ce complètement différent et beaucoup plus dur? (je crois connaitre la réponse et je vais pas beaucoup dormir encore moi )
    Mon responsable veut qu'on puisse par exemple dans un octet mettre 8 booléens ou un booléen et un énumératif (pouvant aller de 0 a 127 donc). Plus généralement il veuille que je puisse écrire ou je veux, ce que je veux sans modifier ce qu'il y a autour. Quelqu'un a une corde ou un avis sur la manière à procéder?

  4. #4
    Expert confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2012
    Messages
    1 711
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2012
    Messages : 1 711
    Points : 4 442
    Points
    4 442
    Par défaut
    C'est exactement le même principe.

    Au lieu de lire/écrire des octets, on lit/écrit des bits.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    unsigned char val = 0;
     
    val |= (1 << 3); // mise à 1 du 4ème bit (en partant de la droite)
    val &= ~(1 << 3); // mise à 0 du 4éme bit (en partant de la droite toujours.)

  5. #5
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Citation Envoyé par DarKaa Voir le message
    Merci beaucoup ça fonctionne parfaitement.
    Et si maintenant l'étape d'après c'était non plus d'écrire ou de lire des octets mais plutôt des bits, serait ce complètement différent et beaucoup plus dur? (je crois connaitre la réponse et je vais pas beaucoup dormir encore moi )
    Mon responsable veut qu'on puisse par exemple dans un octet mettre 8 booléens ou un booléen et un énumératif (pouvant aller de 0 a 127 donc). Plus généralement il veuille que je puisse écrire ou je veux, ce que je veux sans modifier ce qu'il y a autour. Quelqu'un a une corde ou un avis sur la manière à procéder?
    Salut,

    Tu n'as qu'à dire que, au niveau du processeur, tout est déjà écrit sous la forme de bits

    Plus sérieusement: un ordinateur n'est jamais qu'une machine qui fonctionne (pour l'instant du moins) avec une multitude d'interrupteurs qui laissent passer le courent (ca vaut 1 par convention) ou non (ca vaut alors 0 par convention).

    Un byte (que l'on traduit de manière indue par octet en francais) n'est jamais qu'une suite de (on va dire 8, uniquement pour aller avec l'octet , bien que ce ne soit pas forcément juste) interrupteurs pris ensemble.

    Si tu veux pouvoir travailler au bit à bit, l'une des solutions les plus simples consiste sans doute à travailler sur une énumération.

    Les valeurs énumérées seraient un peu particulières dans le sens où elles seraient toutes représentable avec un seul bit. Elle prendrait alors la forme de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    enum BitsField{
       zero   = 0,     // qui l'eut cru ??? :D
       un     = 1,     // vaut 1 
       deux   = 1<<1 , //décalage de deux bits vers la gauche, correspond à 1*2
       trois  = 1 <<2, // correspond à 1*2*2 = 4
       quatre = 1<<3,  // correspond à 1*2*2*2 = 8
       cinq   = 1<<4,  // correspond à 1*2*2*2*2 = 16
       six    = 1<<5,  // correspond à 1*2*2*2*2*2 = 32
       sept   = 1<<6,  // correspond à 1*2*2*2*2*2*2 = 64
       huit    = 1<<7, // correspond à 1*2*2*2*2*2*2*2 = 128
    };
    Une fois que tu as cela, tu peux déjà définir la valeur de chaque bit, mais il peut sembler intéressant de préciser les quelques opérateur de manipulation de bits:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
      inline BitsField
      operator&(BitsField a, BitsField b)
      { return BitsField(static_cast<int>(a) & static_cast<int>(b)); }
     
      inline BitsField
      operator|(BitsField a, BitsField b)
      { return BitsField(static_cast<int>(a) | static_cast<int>(b)); }
     
      inline BitsField
      operator^(BitsField a, BitsField b)
      { return BitsField(static_cast<int>(a) ^ static_cast<int>(b)); }
     
      inline BitsField
      operator~(BitsField a)
      { BitsField(~static_cast<int>(a)); }
     
      inline const BitsField&
      operator|=(BitsField & a, BitsField b)
      { return a = a | b; }
     
      inline const BitsField&
      operator&=( BitsField & a, BitsField b)
      { return a = a & b; }
     
      inline const BitsField&
      operator^=(BitsField & a, BitsField b)
      { return a = a ^ b; }
    De cette manière, tu peux facilement assembler les différentes valeurs:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
      int main(){
        BitsField a(un);
        BitsField b(deux);
        BitsField c = a|b;
        std::cout<< a<<" "<<b<<" "<<c<<std::endl;
      }
    donnera la sortie Tu peux aussi assez facilement vérifier si un bit est mis à un ou à 0 sous une forme proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    int main(){
        BitsField a=un | deux | trois |quatre ; //00001111 en binaire
        std::cout<<" bit un  vaut 1 ? "<<std::boolalpha<<(a& un) <<std::endl
                 <<" bit cinq vaut 1 ? "<<std::boolalpha<<(a &cinq);
      }
    aura pour sortie
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    bit un vaut un ? true
    bit cinq vaut 1? false
    tu peux inverser la valeur d'un (ou de plusieurs) bit(s) particulier(s) indépendamment de sa (leur)valeur d'origine (s'il vaut 1 avant, il vaut 0 après et inversement):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
      int main(){
        BitsField a=un | deux | trois |quatre ; //00001111 en binaire
        std::cout<<"avant: "<<a<<std::endl;
         a^=trois;
         std::cout<<"apres : "<<a<<std::endl;
         a^=trois;
         std::cout<<"revenons a la valeur d'origine :"<<a<<std::endl
                  <<"et changeons la valeur du cinquieme bit : ";
         a^=cinq;
         std::cout<<a<<std::endl;
         std::cout<<"inverson la valeur de deux bits (le 3eme et le 5eme) :";
         BitsField b=trois |cinq;
         a^=b;
         std::cout<<a<<std::endl;
      }
    te donnera la sortie
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    avant: 15
    apres : 11
    revenons a la valeur d'origine : 15
    et changeons la valeur du cinquieme bit : 31
    inverson la valeur de deux bits (le 3eme et le 5eme) : 11
    Bref, tu peux t'amuser comme un petit fou

    Et bien sur, l'ordre dans lequel tu introduit les valeur n'a aucune espèce d'importance, du moment que tu utilises le bon opérateur, et tu peux utiliser les opérateurs de comparaison:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
      int main(){
        BitsField a=un | deux | trois |quatre ; //00001111 en binaire
        BitsField b=un | deux | cinq |quatre ;  //00011011 en binaire
        std::cout<<"avant :"<<a <<" "<<b<<std::endl;
        if(a!= b){
            std::cout<<"oups je me suis gouru "<<std::endl;
            b^= (cinq | trois);
        std::cout<<"apres :"<<a <<" "<<b<<std::endl;
        }
     
      }
    donnera la sortie
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    avant 15 27
    oups je me suis gouru
    apres 15 15
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  6. #6
    Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2011
    Messages
    91
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Val de Marne (Île de France)

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

    Informations forums :
    Inscription : Décembre 2011
    Messages : 91
    Points : 48
    Points
    48
    Par défaut
    Merci Iradrille et koala01 pour ces explications.
    Donc maintenant si j'ai un espace mémoire E de N octets et une variable de type T, qui doit être à l'adresse A, d'access Size de S, de lsb L, de msb M et de valeur V.
    Il me faut une fonction qui aille à l'adresse A dans E, et qui dans les S octets écrive/lise du bit L à M chacun des bits de la conversion de V en binaire.

    Quand j'y pense j'ai le doute qu'il va falloir qu'extraie la zone et peut être la swaper en fonction de l'endianess avant d'écrire dans la zone et la réinsérer. A confirmer. RIP

  7. #7
    Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2011
    Messages
    91
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Val de Marne (Île de France)

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

    Informations forums :
    Inscription : Décembre 2011
    Messages : 91
    Points : 48
    Points
    48
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    template <class T>
    void read(T& val, const unsigned char* data, int msb, int lsb, bool big_endian=true)
    {
        const size_t size = sizeof(T);
        unsigned char *ptr = reinterpret_cast<unsigned char*>(&val);
        for(size_t i=0; i<size; ++i)
            ptr[big_endian ? size-i-1: i] = data[i];
        binary(val);
        val <<= lsb;
        val >>= (sizeof(val) * CHAR_BIT - msb - 1);
    Permet il bien de lire une taille T d'octet(s) et bien pendre les bits de lsb à msb ?

  8. #8
    Membre émérite
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 764
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 764
    Points : 2 705
    Points
    2 705
    Par défaut
    Tu devrais lire le n° de juin de Linux Magazine.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Lecture/Ecriture en binaire
    Par benito9253 dans le forum Windows Forms
    Réponses: 15
    Dernier message: 09/10/2009, 00h35
  2. Lecture et ecriture fichier binaire
    Par gedonet dans le forum VB 6 et antérieur
    Réponses: 3
    Dernier message: 20/04/2009, 19h51
  3. lecture ecriture fichier binaire
    Par jonckers dans le forum C++Builder
    Réponses: 2
    Dernier message: 27/04/2007, 09h12
  4. Réponses: 22
    Dernier message: 22/12/2006, 18h01
  5. Réponses: 5
    Dernier message: 02/10/2006, 22h54

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