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 :

erreur WTF lecture fichier binaire


Sujet :

C++

  1. #1
    Membre éprouvé
    Homme Profil pro
    sans activité
    Inscrit en
    Janvier 2016
    Messages
    76
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : sans activité

    Informations forums :
    Inscription : Janvier 2016
    Messages : 76
    Par défaut erreur WTF lecture fichier binaire
    Bonjour à toutes et tous.

    En général, je trouve plus ou moins facilement les réponses à mes problèmes sur le net (cours, tuto ou forum) mais là...

    Je travail sur un module de lecture/écriture de fichier en mode binaire. J'ai donc fais simple pour l'instant :
    -deux fonctions, une lire et une écrire
    -un main qui teste les deux fonctions avec du texte (uniquement pour le test car la finalité est bien avec du binaire)

    Mon problème est le suivant, j'écris ma donnée dans le fichier -> OK, pas de problème; Je lis est affiche ma donnée lu dans le fichier -> lecture du fichier + données n'étant pas dans le fichier???; Je ne comprends pas d'où viennent ces données, si quelqu'un à une idée, je suis preneur.

    Voici mon code :

    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
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
     
    #include <fstream>
    #include <iostream>
     
    using namespace std;
     
    char* lire(const char* nomfichier)
    {
        int size;
        char * memblock = NULL;
     
        ifstream file (nomfichier, ios::in|ios::binary|ios::ate);
        if (file.is_open())
        {
        size = file.tellg();
     
    	//POUR TESTER LA TAILLE DE CE QUE J'ECRIS DANS LE FICHIER
    	cout << "size in read : " << size << endl;
     
    	memblock = new char [size];
     
        file.seekg (0, ios::beg);
     
    	//LECTURE DU FICHIER AVEC LA BONNE TAILLE VERIFIEE PLUS HAUT
    	file.read (memblock, size);
     
    	//ICI RIEN NE VA PLUS.... WTF
        cout << memblock << " : " << std::char_traits<char>::length(memblock) << '\n' << endl;
        file.close();
        }
        else cout << "Unable to open file";
     
        return memblock;
    }
     
    void ecrire(const char* nomfichier, const char* data)
    {
        int size;
        std::ofstream file (nomfichier, ios::out|ios::binary);
     
    	//TEST DE LA TAILLE EN ECRITURE -> OK
        size = std::char_traits<char>::length(data);
        cout << "size in write : " << size << endl;
        file.write (data, size);
        file.close();
    }
     
     
     
    int main(int argc, char *argv[])
    {
        string data;
        data = "TEST, TEST 1, TEST 2";
     
    	//TEST DE LA DONNEE ET DE SA TAILLE
        cout << data << ' ' << std::char_traits<char>::length(data.c_str()) << '\n' << endl;
     
        ecrire("test.txt", data.c_str());
     
        data = lire("test.txt");
     
        cout << data << '\n' << endl;
     
     
        return 0;
    }

    Et voici ce que j'obtiens en sortie

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    TEST, TEST 1, TEST 2 20
     
    size in write : 20
    size in read : 20
    TEST, TEST 1, TEST 2³²■▀└XÈ#♠Z : 30
     
    TEST, TEST 1, TEST 2³²■▀└XÈ#♠Z
    Comme vous le constatez, je lui demande de lire 20 octets dans mon fichier et le résultat en fait 30!!!

    Merci d'avance.


    PS : -système VISTA 32bits, IDE Codeblocks 13.12, compilateur Mingw32 (je ne me rappelle plus la version, ce n'est pas celle de codeblocks)

  2. #2
    Expert confirmé
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Décembre 2015
    Messages
    1 599
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Décembre 2015
    Messages : 1 599
    Par défaut
    Bonjour,

    Il y a bien 20 octets écrits et 20 octets lus. La fonction marche, mais ...
    std :: char_traits<char> :: length() retourne le longueur d'une chaîne terminée par 0.
    Le zéro n'est pas dans la chaîne sauvée.
    Un texte sans terminateur est aléatoire au delà du dernier caractère.
    En transmettant : size = std :: char_traits<char> :: length(data) +1 caractères, l'illusion de défaut devrait disparaître avec 21 octets écrits et lus.

  3. #3
    Membre éprouvé
    Homme Profil pro
    sans activité
    Inscrit en
    Janvier 2016
    Messages
    76
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : sans activité

    Informations forums :
    Inscription : Janvier 2016
    Messages : 76
    Par défaut
    Je viens de tester, effectivement, ta solution fonctionne, je t'en remercie mais cette solution est-elle valable avec de vrais binaires?

  4. #4
    Expert confirmé
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Décembre 2015
    Messages
    1 599
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Décembre 2015
    Messages : 1 599
    Par défaut
    Les binaires n'ont pas de terminateur (on raisonne en octets)
    Le code marchait, le +1 c'est pour les chaînes (avec un caractère supplémentaire.)

  5. #5
    Membre éprouvé
    Homme Profil pro
    sans activité
    Inscrit en
    Janvier 2016
    Messages
    76
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : sans activité

    Informations forums :
    Inscription : Janvier 2016
    Messages : 76
    Par défaut
    Donc après plusieurs test avec des données binaires, l'octet supplémentairement ne dérange nullement. J'ai donc décidé de le laisser.

    Je considère donc ce post comme résolu!

    Mais du coup ce pose le problème des données binaires en C++ : Est-il possible de contourner le problème des Little/Big Endian et également celui de la taille réelle des variables car même avec l'utilisation du style uint64_t je constate que le compilateur coupe la taille réelle des données en mémoire. Exemple si ma variable contient un petit nombre, inférieur à 256, la variable ne fait qu'un seul octet en mémoire.


    PS: je vais ouvrir un nouveau poste pour cette nouvelle question, ICI

  6. #6
    Expert confirmé

    Avatar de dragonjoker59
    Homme Profil pro
    Software Developer
    Inscrit en
    Juin 2005
    Messages
    2 032
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Bas Rhin (Alsace)

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

    Informations forums :
    Inscription : Juin 2005
    Messages : 2 032
    Billets dans le blog
    12
    Par défaut
    Citation Envoyé par rnr72 Voir le message
    même avec l'utilisation du style uint64_t je constate que le compilateur coupe la taille réelle des données en mémoire. Exemple si ma variable contient un petit nombre, inférieur à 256, la variable ne fait qu'un seul octet en mémoire.
    Ca me semble louche. Comment écris-tu tes données binaires?
    Si vous ne trouvez plus rien, cherchez autre chose...

    Vous trouverez ici des tutoriels OpenGL moderne.
    Mon moteur 3D: Castor 3D, presque utilisable (venez participer, il y a de la place)!
    Un projet qui ne sert à rien, mais qu'il est joli (des fois) : ProceduralGenerator (Génération procédurale d'images, et post-processing).

  7. #7
    Membre Expert
    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
    Par défaut
    Je viens de tester, j'observe la même chose, c'est étrange.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    std::ofstream f64("64.dat", std::ios::binary);
    f64 << std::uint64_t(42); // f64.dat fait 2 octets, et contient "42" -> pas d'écriture binaire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    std::ofstream f64("64.dat", std::ios::binary);
    std::uint a = 42;
    f64.write((char const*)&a, sizeof(a)); // f64.dat fait 8 octets, et contient "*\0\0\0\0\0\0\0" -> écriture binaire, mais c'est pas vraiment la façon de faire

  8. #8
    Membre éprouvé
    Homme Profil pro
    sans activité
    Inscrit en
    Janvier 2016
    Messages
    76
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : sans activité

    Informations forums :
    Inscription : Janvier 2016
    Messages : 76
    Par défaut
    Ce n'est pas étrange, je pense que cela vient de l'optimisation du compilateur...

    Mais je t'invite à venir en discuté ICI

  9. #9
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 392
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 392
    Par défaut
    Citation Envoyé par Iradrille Voir le message
    Je viens de tester, j'observe la même chose, c'est étrange.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    std::ofstream f64("64.dat", std::ios::binary);
    f64 << std::uint64_t(42); // f64.dat fait 2 octets, et contient "42" -> pas d'écriture binaire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    std::ofstream f64("64.dat", std::ios::binary);
    std::uint a = 42;
    f64.write((char const*)&a, sizeof(a)); // f64.dat fait 8 octets, et contient "*\0\0\0\0\0\0\0" -> écriture binaire, mais c'est pas vraiment la façon de faire
    La seule chose qui me paraisse étrange là-dedans, c'est que tu sois sur un système à modèle ILP64 (où les int font 64 bits) alors que les systèmes les plus communs sur PC tendent à utiliser les modèles LLP64 (Windows) et LP64 (Linux)...

    Dans tous les cas, les opérateurs << et >>, appliqués aux flux, ne connaissent que le texte, quel que soit le mode d'ouverture du flux (d'ailleurs, les flux non-ofstream ont-ils un mode d'ouverture?). C'est une des raisons pour lesquelles je considère le support des fichiers binaires par C++ comme maladroitement "ajouté après le reste".
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  10. #10
    Membre Expert
    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
    Par défaut
    Problème de copier collé, c'est un std::uint64_t.

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

Discussions similaires

  1. Lecture fichier binaire et inversion d'octets
    Par zoro_le_renard dans le forum Fortran
    Réponses: 8
    Dernier message: 17/07/2007, 20h35
  2. Lecture fichier binaire
    Par djidji dans le forum Langage
    Réponses: 1
    Dernier message: 09/11/2006, 11h58
  3. Réponses: 5
    Dernier message: 02/10/2006, 22h54
  4. Lecture fichier binaire
    Par kek_net dans le forum Langage
    Réponses: 5
    Dernier message: 07/08/2006, 19h37
  5. Lecture fichier binaire
    Par gabule dans le forum Entrée/Sortie
    Réponses: 4
    Dernier message: 30/05/2006, 15h53

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