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

SL & STL C++ Discussion :

ifstream operateur >> ne fonctionne pas


Sujet :

SL & STL C++

  1. #1
    Expert confirmé
    Avatar de shenron666
    Homme Profil pro
    avancé
    Inscrit en
    Avril 2005
    Messages
    2 524
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : avancé

    Informations forums :
    Inscription : Avril 2005
    Messages : 2 524
    Points : 5 184
    Points
    5 184
    Par défaut ifstream operateur >> ne fonctionne pas
    Bonjour,

    Est-ce que quelqu'un pourrait me dire pourquoi ce code ne fonctionne pas ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    std::ifstream ficInTest("data.dat", std::ios_base::in | std::ios_base::binary);
     
    unsigned long nTest;
    ficInTest >> nTest;
    Le fichier est bien ouvert mais la donnée n'est pas lue
    avec la méthode read ça fonctionne
    Tutoriels OpenGL
    Je ne répondrai à aucune question en MP
    - Si c'est simple tu dis que c'est compliqué et tu le fait
    - Si c'est compliqué tu dis que c'est simple et tu le sous-traite ou le fait faire par un stagiaire.

  2. #2
    Membre émérite

    Inscrit en
    Mai 2008
    Messages
    1 014
    Détails du profil
    Informations forums :
    Inscription : Mai 2008
    Messages : 1 014
    Points : 2 252
    Points
    2 252
    Par défaut
    Bonjour,
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    std::ifstream ficInTest("data.dat", std::ios_base::in | std::ios_base::binary);
    Il me semble que l'opérateur >> est réservé pour la lecture de texte formaté. Pour lire du texte brut, voire du binaire il faut utiliser read.

  3. #3
    Expert confirmé
    Avatar de shenron666
    Homme Profil pro
    avancé
    Inscrit en
    Avril 2005
    Messages
    2 524
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : avancé

    Informations forums :
    Inscription : Avril 2005
    Messages : 2 524
    Points : 5 184
    Points
    5 184
    Par défaut
    C'est bien ce que je pensais, bien que je trouve cela étrange de ne pas avoir implémenté ces opérateurs pour du binaire.

    Merci pour ta réponse
    Tutoriels OpenGL
    Je ne répondrai à aucune question en MP
    - Si c'est simple tu dis que c'est compliqué et tu le fait
    - Si c'est compliqué tu dis que c'est simple et tu le sous-traite ou le fait faire par un stagiaire.

  4. #4
    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
    Salut, désolé de faire remonter le poste, mais
    Citation Envoyé par shenron666 Voir le message
    C'est bien ce que je pensais, bien que je trouve cela étrange de ne pas avoir implémenté ces opérateurs pour du binaire.
    Non, c'est tout à fait normal: il est strictement impossible de formater une succession de 1 et de 0 sur laquelle nous n'avons strictement aucune emprise

    Finalement, lorsque tu ouvre ton fichier en mode "binaire" (bien que le terme soit particulièrement mal choisi ), il n'y a strictement rien qui t'empêche de lire les bytes d'un entier ou d'un réel "caractères par caractères" (dont certains auront des valeurs non graphiques) ou l'inverse (de lire quatre caractères d'un coup dans un entier, par exemple)...

    Evidemment, il faut comprendre le "rien ne t'empêche" dans le sens où la tu n'a aucun moyen de faire la différence dans ton fichier entre ce qui est un byte destiné à un caractère et ce qui en est un destiné à un entier... Il est clair que, pour l'utilisation de la donnée lue, il est largement préférable de la lire dans le type adéquat
    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

  5. #5
    Expert confirmé
    Avatar de shenron666
    Homme Profil pro
    avancé
    Inscrit en
    Avril 2005
    Messages
    2 524
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : avancé

    Informations forums :
    Inscription : Avril 2005
    Messages : 2 524
    Points : 5 184
    Points
    5 184
    Par défaut
    rien n'empêcherait non plus d'avoir un opérateur pour simplement lire/écrire les différents types binaires en série (sbyte, ubyte, sshort, ushort, slong, ulong, ect...) sans formatage, vu que le fichier est ouvert en mode binaire

    pour lire 10 <T> on est "obligé" de faire 10 appels de stream.read((cast T)&var, sizeof(T))
    je trouve pas ça très propre ni très c++

    je trouve dommage que ça n'ai pas été implémenté, ou alors ça l'est et j'aimerai bien trouver
    peut-etre dans boost ?

    j'ai pas trop eu le temps de chercher, je suis occupé avec boost::iostreams et les archives zip
    si quelqu'un a une proposition je suis preneur, sinon je chercherai dès que j'ai un moment
    Tutoriels OpenGL
    Je ne répondrai à aucune question en MP
    - Si c'est simple tu dis que c'est compliqué et tu le fait
    - Si c'est compliqué tu dis que c'est simple et tu le sous-traite ou le fait faire par un stagiaire.

  6. #6
    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
    Mais le terme important dans "opérateur d'entrée (de sortie) formatée" est, justement... formaté

    Or le formatage ne trouve sa raison d'être que lorsque tu travailles au minimum avec "autre chose qu'une succession sans queue ni tête de 1 et de 0"...

    Or, comme je l'ai mal exprimé plus haut, tu ne peux pas considérer les informations qui se trouvent à l'intérieur d'un fichier binaire autrement que comme une succession de 1 et de 0...

    En effet, imagine un instant une structure "toute simple" proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    struct S
    {
        int i;
        char c;
        double f;
    };
    qui, chez moi, correspond à une structure de 16 bytes, et qui, du fait des contraintes d'alignement mémoire se présente en mémoire sous la forme de
    • 4 bytes pour i
    • 1 byte pour c
    • 3 bytes "inutilisés" (d'alignement)
    • 8 bytes pour d

    Dans un fichier binaire, tu peux, au choix te retrouver soit avec N*16 bytes (d'avoir écrit les trois bits inutilisés), soit avec seulement N*13 bytes.

    Tant que tu accédera au données de manière séquentielle, et pour autant que tu suive la même politique lors de la lecture que celle utilisée lors de l'écriture (enlever ou non les trois bits inutilisés), tu n'auras aucun problème: tu lira tes données une à une

    Mais si tu décide d'aller à la Xième donnée, et que, marqué pas de bol, tu te trompes dans ta formule pour calculer la position dans le fichier sous la forme de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    file.seekg(pos*16+1,ios_base::beg); //pas de bol, c'était pos*16 :P
    Lorsque tu va essayer de lire les données, tu va lire ton entier, ton caractère, passer trois bytes inutilisés et terminer par la lecture de ton double "comme une lettre à la poste", et il n'y aura strictement rien qui pourra te permettre de remarquer que la lecture est décalée d'un byte:
    • Pour ton entier, tu lira les trois derniers bytes de l'entier et le byte normalement dévolu au caractère
    • pour le caractère, tu lira en réalité le premier byte inutilisé
    • pour le double, tu lira les 7 derniers bytes dévolu au double et le premier byte de l'entier de la structure suivante

    Et la lecture s'effectuera de manière tout à fait correcte...

    Mais tu obtiendra des données pour le moins incohérentes

    Par contre, si tu envisage ton fichier comme un fichier texte, tu n'a pas de problème: ce que tu lis sera d'office un caractère...

    Si l'on parle d'entrée formatée pour un fichier texte, c'est entre autre du fait qu'il existe un format clairement défini pour chaque type que l'on peut rencontrer:
    • un entier est composé
      • d'un signe négatif éventuel
      • d'une succession de chiffres (caractères dont la représentation s'étend entre '0' et '9')
    • un double sera composé (s'il n'est pas écrit en notation scientifique)
      • d'un signe négatif éventuel
      • d'un certain nombre de chiffres
      • d'une virgule éventuelle
      • d'un certain nombre de chiffres après la virgule
    • La plupart des données significatives seront représentées sous la forme de caractères "affichables" (dont la valeur est supérieure ou égale à 32 si tu suis la table ASCII)
    • que les données significatives seront séparées, outre utilisation d'un symbole particulier pour respecter un format précis (CSV) par un caractère qui peut être considéré comme un espace (espace, tabulation, retour à la ligne...)
    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

  7. #7
    Expert confirmé
    Avatar de shenron666
    Homme Profil pro
    avancé
    Inscrit en
    Avril 2005
    Messages
    2 524
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : avancé

    Informations forums :
    Inscription : Avril 2005
    Messages : 2 524
    Points : 5 184
    Points
    5 184
    Par défaut
    Citation Envoyé par koala01 Voir le message
    Mais le terme important dans "opérateur d'entrée (de sortie) formatée" est, justement... formaté
    sauf que les opérateurs >> et << sont des opérateurs d'entrée et de sortie de flux
    il n'est nullement question de formatage dans aucune documentation que j'ai lu jusqu'ici
    edit : je veux dire que je n'ai vu dans aucune doc << et >> décris comme des opérateurs formatés

    Citation Envoyé par koala01
    En effet, imagine un instant une structure "toute simple" proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    struct S
    {
        int i;
        char c;
        double f;
    };
    qui, chez moi, correspond à une structure de 16 bytes, et qui, du fait des contraintes d'alignement mémoire se présente en mémoire sous la forme de
    • 4 bytes pour i
    • 1 byte pour c
    • 3 bytes "inutilisés" (d'alignement)
    • 8 bytes pour d

    Dans un fichier binaire, tu peux, au choix te retrouver soit avec N*16 bytes (d'avoir écrit les trois bits inutilisés), soit avec seulement N*13 bytes.
    ta structure n'étant pas un type standard, tu es obligé d'écrire le code des opérateurs ou de faire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ficIn >> S.i >> S.c >> S.f;
    l'alignement des données n'a aucun rapport avec le "problème" que je soulève
    Tutoriels OpenGL
    Je ne répondrai à aucune question en MP
    - Si c'est simple tu dis que c'est compliqué et tu le fait
    - Si c'est compliqué tu dis que c'est simple et tu le sous-traite ou le fait faire par un stagiaire.

  8. #8
    Expert éminent

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Points : 6 911
    Points
    6 911
    Par défaut
    Citation Envoyé par shenron666 Voir le message
    sauf que les opérateurs >> et << sont des opérateurs d'entrée et de sortie de flux
    il n'est nullement question de formatage dans aucune documentation que j'ai lu jusqu'ici
    edit : je veux dire que je n'ai vu dans aucune doc << et >> décris comme des opérateurs formatés
    La norme les decrits comme tels (27.6.1.2 Formatted input functions, 27.6.2.6 Formatted output functions).
    Les MP ne sont pas là pour les questions techniques, les forums sont là pour ça.

  9. #9
    Membre émérite

    Inscrit en
    Mai 2008
    Messages
    1 014
    Détails du profil
    Informations forums :
    Inscription : Mai 2008
    Messages : 1 014
    Points : 2 252
    Points
    2 252
    Par défaut
    sauf que les opérateurs >> et << sont des opérateurs d'entrée et de sortie de flux
    il n'est nullement question de formatage dans aucune documentation que j'ai lu jusqu'ici
    Ho que si.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    std::cout << std::hew << setw(4) << truc << std::endl;
    J'ai remis la main sur un livre qui décrit plus en détail la librairie IOStream.

    En gros, cette librairie est divisé en deux couches : la couche transport et la couche format.
    La couche transport est géré par les streambuf, qui possèdent deux classes filles spécialisées stringbuf et filebuf.
    La couche format est gérée par les istream, ostream, iostream en coopération avec les locales. Ces classes possèdent en outre un pointeur vers leur streambuf. Toute la libraire est conçue pour lire du texte formaté. Il n'y a que deux manières pour lire et écrire du non formaté :
    * Utiliser les fonctions spéciales read() et write().
    * Utiliser un filebuf directement.

    Plus de détails ici :

    Citation Envoyé par Standart C++ IOStream and Locales, Advanced programmer's guide and reference
    System-specific conversions. The open mode flag binary has the effect of suppressing automatic conversions performed by underlying system services. The representation of text files varies among operating system. For example, the end of a line in a UNIX environment is represented by the linefeed character '\n', whereas on Microsoft operating system the end of the line consists of two character, carriage return '\r' and linefeed '\n'. And operating system I/O functions therefore perform automatic conversions, such as converting between "\r\n" and '\n'.
    The open mode flag binary has the effect of suppressing such automatic conversion. Basically, the binary mode flag is passed on to the respective operating system's service function, wich mean that in principles all system-specific conversions will be suppressed, not just the carriage return / linefeed handing. The effect of the binary open mode is frequently misunderstood. It does not put the inserters and extractors of IOStreams into a binary mode in the sense of suppressing the formatting they usually perform. Binary input and output, in the sense of unformatted I.O, is done via certain member function of the stream classes istream:read) and ostream::write()
    Citation Envoyé par Standart C++ IOStream and Locales, Advanced programmer's guide and reference
    Unformatted Input/Output
    IOStream is typically used for formatted input and output of text. In addition to the shift operators that performed formatted input and output, the stream classes also provide a set of functions for unformatted input and output.
    ... suit la description de read() et write()...

  10. #10
    Expert confirmé
    Avatar de shenron666
    Homme Profil pro
    avancé
    Inscrit en
    Avril 2005
    Messages
    2 524
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : avancé

    Informations forums :
    Inscription : Avril 2005
    Messages : 2 524
    Points : 5 184
    Points
    5 184
    Par défaut
    où puis-je trouver la documentation de cette norme ?
    Citation Envoyé par Arzar Voir le message
    Ho que si.
    merci de lire sans oublier des mots
    Citation Envoyé par shenron666
    il n'est nullement question de formatage dans aucune documentation que j'ai lu jusqu'ici
    edit : je veux dire que je n'ai vu dans aucune doc << et >> décris comme des opérateurs formatés
    Tutoriels OpenGL
    Je ne répondrai à aucune question en MP
    - Si c'est simple tu dis que c'est compliqué et tu le fait
    - Si c'est compliqué tu dis que c'est simple et tu le sous-traite ou le fait faire par un stagiaire.

  11. #11
    Expert confirmé
    Avatar de shenron666
    Homme Profil pro
    avancé
    Inscrit en
    Avril 2005
    Messages
    2 524
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : avancé

    Informations forums :
    Inscription : Avril 2005
    Messages : 2 524
    Points : 5 184
    Points
    5 184
    Par défaut
    Citation Envoyé par Arzar Voir le message
    Il n'y a que deux manières pour lire et écrire du non formaté :
    * Utiliser les fonctions spéciales read() et write().
    * Utiliser un filebuf directement.
    je t'en propose une troisième, surcharger à sa sauce les opérateurs
    par exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    std::ifstream& operator>>(std::ifstream& in, unsigned char& val)
    {
    	in.read((char*)&val, sizeof(unsigned char));
     
    	return in;
    }
    edit : je me répète, c'est juste que je trouve dommage que les opérateurs soient zappés et on perd la notation C++, le typage et la possibilité de chainer les lectures / écritures
    c'est un avis personnel
    Tutoriels OpenGL
    Je ne répondrai à aucune question en MP
    - Si c'est simple tu dis que c'est compliqué et tu le fait
    - Si c'est compliqué tu dis que c'est simple et tu le sous-traite ou le fait faire par un stagiaire.

  12. #12
    Expert éminent

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Points : 6 911
    Points
    6 911
    Par défaut
    Citation Envoyé par shenron666 Voir le message
    je t'en propose une troisième, surcharger à sa sauce les opérateurs
    par exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    std::ifstream& operator>>(std::ifstream& in, unsigned char& val)
    {
    	in.read((char*)&val, sizeof(unsigned char));
     
    	return in;
    }
    Sainte horreur. La norme defini une fonction template et tu la surcharge dans un autre namespace (ou hors de tout namespace) pour un type de base. C'est chercher des problemes.

    Si tu veux t'amuser a cela, defini tes propres streams (eventuellement en utilisant les streambuf standard pour le transport -- attention aux locales -- et en les faisant descendre de ios_base/basic_ios pour recuperer des choses que tu trouves utiles a ce niveau) mais ne surcharge pas sur {i,o,io}stream ni sur ses descendants, c'est trop de risque de problemes a mon avis.

    (En passant, unsigned char est le type que je n'aurais jamais pris en exemple pour des IO binaires... )
    Les MP ne sont pas là pour les questions techniques, les forums sont là pour ça.

  13. #13
    Membre émérite

    Inscrit en
    Mai 2008
    Messages
    1 014
    Détails du profil
    Informations forums :
    Inscription : Mai 2008
    Messages : 1 014
    Points : 2 252
    Points
    2 252
    Par défaut
    Il y a quand même un truc que je ne comprends pas bien au final
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    std::ifstream ficInTest("data.dat", std::ios_base::in | std::ios_base::binary);
     
    unsigned long nTest;
    ficInTest >> nTest;
    Pourquoi ce code échoue alors qu'un read passe ?
    Le bouquin que j'ai cité explique que std::ios_base::binary est un nom trompeur, car il n'annule pas le formatage, il annule seulement les conversions automatiques faite par le système (comme convertir tous les \n en \n\r) donc l'opérateur>> devrait quand même marcher...
    Qu'est ce que ça donne, en enlevant le mode binary ?

  14. #14
    Expert confirmé
    Avatar de shenron666
    Homme Profil pro
    avancé
    Inscrit en
    Avril 2005
    Messages
    2 524
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : avancé

    Informations forums :
    Inscription : Avril 2005
    Messages : 2 524
    Points : 5 184
    Points
    5 184
    Par défaut
    Citation Envoyé par Jean-Marc.Bourguet Voir le message
    Sainte horreur. La norme defini une fonction template et tu la surcharge dans un autre namespace (ou hors de tout namespace) pour un type de base. C'est chercher des problemes.

    (En passant, unsigned char est le type que je n'aurais jamais pris en exemple pour des IO binaires... )
    c'était juste un exemple
    et puis je peux n'inclure le header que lorsque j'ai besoin des surcharges
    c'est relativement souple de cette manière
    edit : en passant, même unsigned char nécessite un cast puisque read et write attendent un pointeur vers char

    Citation Envoyé par Jean-Marc.Bourguet
    Si tu veux t'amuser a cela, defini tes propres streams (eventuellement en utilisant les streambuf standard pour le transport -- attention aux locales -- et en les faisant descendre de ios_base/basic_ios pour recuperer des choses que tu trouves utiles a ce niveau) mais ne surcharge pas sur {i,o,io}stream ni sur ses descendants, c'est trop de risque de problemes a mon avis.
    c'est quoi votre problème de vouloir tout recoder à chaque fois ?
    c'est justement dans ces cas là qu'il y a plus de risques de problèmes
    pourquoi être aussi restrictif, le c++ a cette souplesse alors autant s'en servir

    Citation Envoyé par Arzar Voir le message
    Le bouquin que j'ai cité explique que std::ios_base::binary est un nom trompeur, car il n'annule pas le formatage
    ou alors ton bouquin est faux
    ou alors les implémentations que j'ai testé (visual 2008 et mingw32) ne le respectent pas
    ou alors... je sais pas, ils parlent de conversion automatique désactivée
    "The open mode flag binary has the effect of suppressing automatic conversions performed by underlying system services."

    Citation Envoyé par Arzar
    Qu'est ce que ça donne, en enlevant le mode binary ?
    l'operateur >> ne lit rien
    read termine sa lecture sur certaines valeurs (0x1A par exemple)
    Tutoriels OpenGL
    Je ne répondrai à aucune question en MP
    - Si c'est simple tu dis que c'est compliqué et tu le fait
    - Si c'est compliqué tu dis que c'est simple et tu le sous-traite ou le fait faire par un stagiaire.

  15. #15
    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
    En fait, std::ios_base::bin (car c'est ce dont il s'agit ) est effectivement trompeur, car, lorsque l'on ne l'utilise pas, nous pouvons avoir l' (la fausse) impression que le fichier n'est pas un fichier binaire, or, strictement tout ce qui se trouve sur un ordinateur est dans un format binaire

    La différence tient dans le fait que, lorsque l'on manipule un fichier dit "texte", nous partons de la convention selon laquelle chaque byte représente bel et bien un caractère

    Plutôt que de parler de "fichier binaire", nous devrions presque plutôt parler de fichier "contenant des données brutes" pour indiquer que les données ne sont ni formatées ni converties (car toute données apparaissant dans un fichier "texte" est convertie en... chaine de caractères )

    Et c'est pourquoi il n'y a pas de raison de permettre l'utilisation des opérateurs de flux formatés sur un fichier "binaire": une donnée brute n'a absolument rien de formatée .

    Comme je l'ai dit plus haut, si tu te positionne mal avant de commencer ta lecture dans un fichier binaire, tu n'a strictement aucune vérification possible pour t'assurer que tu lis bien des données cohérentes, un byte pouvant indifféremment être considéré comme un caractère ou comme l'une des parties de n'importe quel type nécessitant plus d'un byte de large pour permettre la représentation de certaines valeurs.

    De plus, l'erreur de positionnement se répercutera sur l'ensemble des lectures.

    Par contre, si tu te positionne mal dans un fichier "texte" avant de commencer la lecture, au pire tu n'aura qu'une donnée incorrecte mais pas forcément incohérente (tu obtiendra 128 au lieu de 9128), et les données suivantes seront lues correctement
    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

  16. #16
    Expert éminent

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Points : 6 911
    Points
    6 911
    Par défaut
    Sous Unix et Windows, un fichier est une suite de bytes sans structure supplementaire. Un fichier texte est un fichier qui respecte quelques conventions en plus, mais l'OS n'en est meme pas au courant. Ce n'est pas le cas partout, certains OS ont une notion de fichier texte qui n'est pas simplement une histoire de convention. Et ces OS ont des limitations sur ce qui est possible avec un fichier texte. Ces OS ont aussi d'autres types de fichiers.

    Le C et le C++ ont deux types de fichiers:
    - des fichiers textes, destines a etre compatible avec la notion de fichier texte de l'OS. Avec pour resultat des limitations pour les rendre largement implementables (ne pas pouvoir faire de deplacement ailleurs qu'a un resultat de fgetpos and co, ne pas pouvoir ecrire d'autres caracteres de controle que \t et \n, pouvoir modifier le nombre d'espaces avant \n entre ce qu'on lit et ce qu'on ecrit, necessite de terminer la derniere ligne,...). Sous Unix, aucune de ces limitations a de l'effet. Sous Windows, le seul effet est la transformation de \n en \r\n et donc un decalage possible si on essaie de calculer des deplacements plutot qu'en faire vers une position memorisee (peut-etre aussi CTRL-Z considere comme fin de fichier?).
    - des fichiers binaires, qui n'ont pas ces limitations (on lit exactement ce qu'on a ecrit, on peut calculer des deplacements), mais qui ne sont pas garanti etre compris par l'OS comme fichier texte.
    - (en C, l'implementation peut completer le mode pour acceder aux possibilites supplementaires des fichiers de l'OS, en C++ je ne vois rien d'equivalent)

    C'est tout comme difference. Toutes le reste, y compris les operations d'IO formatees et non formatees sont possibles des deux cotes -- tant qu'on respecte les contraintes dans le cas des fichiers textes. La gestion des jeux de caracteres (appel au codecvt de la locale imbuee en C++ -- ce qui peut modifier les caracteres lus et ecrits) est faite de la meme maniere pour les deux types.

    Note: si j'y pense, je reprendrai les points problematiques dans les messages de koala01 et shenron666 plus tard.
    Les MP ne sont pas là pour les questions techniques, les forums sont là pour ça.

  17. #17
    Expert éminent

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Points : 6 911
    Points
    6 911
    Par défaut
    Citation Envoyé par shenron666 Voir le message
    c'était juste un exemple
    et puis je peux n'inclure le header que lorsque j'ai besoin des surcharges
    c'est relativement souple de cette manière
    Et maintenant, faire exprès que la résolution de surcharge trouve des
    fonctions différentes pour les mêmes paramètres suivant l'endroit où on se
    trouve. Encore quelque chose qui passerait pas la code review si je suis
    dans la salle.

    edit : en passant, même unsigned char nécessite un cast
    puisque read et write attendent un pointeur vers char
    Quelle différence de comportement penses-tu qu'il y a entre ton exemple et
    la fonction standard?

    c'est quoi votre problème de vouloir tout recoder à chaque fois ?
    C'est quoi ton problème à vouloir à tout prix réutiliser du code en dehors
    du contexte pour lequel il a été conçu -- ce qui est déjà problèmatique --
    en utilisant en prime des techniques déconseillées?

    c'est justement dans ces cas là qu'il y a plus de risques de
    problèmes pourquoi être aussi restrictif, le c++ a cette souplesse alors
    autant s'en servir
    Programmer n'est pas un concour d'utilisation des techniques les plus
    tordues possibles. Maintenant, si c'est pour faire une entrée à
    l'équivalent C++ de l'IOCCC, ne te gène
    pas.

    ou alors ton bouquin est faux
    Le bouquin en question est la référence sur le sujet après le norme.

    ou alors les implémentations que j'ai testé (visual 2008 et mingw32)
    ne le respectent pas ou alors... je sais pas,
    Tu n'as pas compris le sujet?

    ils parlent de conversion automatique désactivée "The open mode flag
    binary has the effect of suppressing automatic conversions performed by
    underlying system services."
    Voir mon message précédent (\n -> \r\n et peut-être CTRL-Z considéré comme
    fin de fichier, vieux reliquat de CPM).

    l'operateur >> ne lit rien
    read termine sa lecture sur certaines valeurs (0x1A par exemple)
    CTRL-Z considéré comme fin de fichier confirmé.

    Citation Envoyé par koala01 Voir le message
    La différence tient dans le fait que, lorsque l'on
    manipule un fichier dit "texte", nous partons de la convention selon
    laquelle chaque byte représente bel et bien un caractère
    Et les jeux de caractères multibytes?

    Et c'est pourquoi il n'y a pas de raison de permettre l'utilisation
    des opérateurs de flux formatés sur un fichier "binaire"
    Pour quelle raison interdire?

    Par contre, si tu te positionne mal dans un fichier "texte" avant de
    commencer la lecture,
    Petit rappel: dans un fichier texte tu ne peux te positionner qu'à un
    endroit dont tu as mémorisé la position.

    au pire tu n'aura qu'une donnée incorrecte mais pas forcément
    incohérente (tu obtiendra 128 au lieu de 9128),
    ou toto à la place de 9128 ce qui fait une erreur (fichier contenant toto
    9128 ou 9128 toto)

    et les données suivantes seront lues correctement
    Qu'est-ce qui t'assures que tu vas te resynchroniser?
    Les MP ne sont pas là pour les questions techniques, les forums sont là pour ça.

  18. #18
    Expert confirmé
    Avatar de shenron666
    Homme Profil pro
    avancé
    Inscrit en
    Avril 2005
    Messages
    2 524
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : avancé

    Informations forums :
    Inscription : Avril 2005
    Messages : 2 524
    Points : 5 184
    Points
    5 184
    Par défaut
    Citation Envoyé par koala01 Voir le message
    Plutôt que de parler de "fichier binaire", nous devrions presque plutôt parler de fichier "contenant des données brutes" pour indiquer que les données ne sont ni formatées ni converties (car toute données apparaissant dans un fichier "texte" est convertie en... chaine de caractères )
    ce n'est pas le fichier qui est binaire ou pas mais le mode de lecture du fichier
    on peux aussi bien lire un fichier texte en mode texte avec les flux de conversion ou en mode binaire et gérer soi même (ou pas) la conversion

    Citation Envoyé par koala01
    Comme je l'ai dit plus haut, si tu te positionne mal avant de commencer ta lecture dans un fichier binaire, tu n'a strictement aucune vérification possible pour t'assurer que tu lis bien des données cohérentes
    en mode binaire, ni avec "ma méthode" (surcharge) ni avec ifstream::read
    et c'est pareil en mode texte

    Citation Envoyé par koala01
    De plus, l'erreur de positionnement se répercutera sur l'ensemble des lectures.
    si tu lis une donnée fausse en mode texte et que tu ne le détecte pas c'est pas mieux

    Citation Envoyé par koala01
    ]Par contre, si tu te positionne mal dans un fichier "texte" avant de commencer la lecture, au pire tu n'aura qu'une donnée incorrecte mais pas forcément incohérente (tu obtiendra 128 au lieu de 9128)
    c'est tout aussi important d'avoir une donnée bonne qu'une donnée cohérente
    je dirai même qu'une donnée cohérente et fausse c'est plus dangereux qu'une donnée incohérente car la donnée fausse si elle est juste tronquée ça peut avoir des répercussions inattendues
    Tutoriels OpenGL
    Je ne répondrai à aucune question en MP
    - Si c'est simple tu dis que c'est compliqué et tu le fait
    - Si c'est compliqué tu dis que c'est simple et tu le sous-traite ou le fait faire par un stagiaire.

  19. #19
    Expert confirmé
    Avatar de shenron666
    Homme Profil pro
    avancé
    Inscrit en
    Avril 2005
    Messages
    2 524
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : avancé

    Informations forums :
    Inscription : Avril 2005
    Messages : 2 524
    Points : 5 184
    Points
    5 184
    Par défaut
    Citation Envoyé par Jean-Marc.Bourguet Voir le message
    Et maintenant, faire exprès que la résolution de surcharge trouve des fonctions différentes pour les mêmes paramètres suivant l'endroit où on se trouve. Encore quelque chose qui passerait pas la code review si je suis dans la salle.
    oulà, oui bon ok, j'ai compris j'insiste pas de ce côté là

    Citation Envoyé par Jean-Marc.Bourguet
    Quelle différence de comportement penses-tu qu'il y a entre ton exemple et la fonction standard?
    mon exemple lit la donnée
    la fonction template non
    à part ça...

    Citation Envoyé par Jean-Marc.Bourguet
    C'est quoi ton problème à vouloir à tout prix réutiliser du code en dehors du contexte pour lequel il a été conçu -- ce qui est déjà problèmatique -- en utilisant en prime des techniques déconseillées?
    je ne comprend pas vraiment pourquoi elles sont déconseillées
    j'ai plutot l'impression que c'est psychologique

    Citation Envoyé par Jean-Marc.Bourguet
    Le bouquin en question est la référence sur le sujet après le norme.
    Tu n'as pas compris le sujet?
    je n'ai peut-etre pas compris le sujet
    mais je ne comprend pas cette remarque non plus

    Citation Envoyé par Jean-Marc.Bourguet
    Voir mon message précédent (\n -> \r\n et peut-être CTRL-Z considéré comme fin de fichier, vieux reliquat de CPM).
    Citation Envoyé par Jean-Marc.Bourguet
    Pour quelle raison interdire?
    j'aimerai bien savoir aussi

    bon si je résume vos remarques et si je veux pouvoir rester dans la même salle que Jean-Marc il faut que je crée ma propre classe de lecture binaire avec ses opérateurs
    merci de perdre votre temps à m'expliquer et à me taper sur les doigts
    Tutoriels OpenGL
    Je ne répondrai à aucune question en MP
    - Si c'est simple tu dis que c'est compliqué et tu le fait
    - Si c'est compliqué tu dis que c'est simple et tu le sous-traite ou le fait faire par un stagiaire.

  20. #20
    Expert éminent

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Points : 6 911
    Points
    6 911
    Par défaut
    Citation Envoyé par shenron666 Voir le message
    ce n'est pas le fichier qui est binaire ou pas mais le mode de lecture du fichier
    on peux aussi bien lire un fichier texte en mode texte avec les flux de conversion ou en mode binaire et gérer soi même (ou pas) la conversion
    Rien ne garanti que ce soit possible.

    Citation Envoyé par shenron666 Voir le message
    mon exemple lit la donnée
    la fonction template non
    à part ça...
    Les deux vont faire a peu près la même chose (je ne suis pas sûr de la gestion d'erreur et la version standard doit tenir compte de skipws si je ne m'absuse pas).

    je ne comprend pas vraiment pourquoi elles sont déconseillées
    - Le risque de faire accidentellement ce que tu suggérais plus haut de faire volontairement est trop grand.
    - Tu écris du code dont l'effet va surprendre quelqu'un qui n'est pas au courant de ta manipulation.
    Les MP ne sont pas là pour les questions techniques, les forums sont là pour ça.

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. Réponses: 6
    Dernier message: 27/01/2004, 11h14
  2. [FP]Writeln ne fonctionne pas !
    Par néo333 dans le forum Turbo Pascal
    Réponses: 4
    Dernier message: 01/11/2003, 23h47
  3. UNION qui ne fonctionne pas
    Par r-zo dans le forum Langage SQL
    Réponses: 7
    Dernier message: 21/07/2003, 10h04
  4. Un Hint sur un PopupMenu ne fonctionne pas !!??
    Par momox dans le forum C++Builder
    Réponses: 6
    Dernier message: 26/05/2003, 16h48
  5. ca ne fonctionne pas (generateur auto-incrémentant)
    Par tripper.dim dans le forum SQL
    Réponses: 7
    Dernier message: 26/11/2002, 00h10

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