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 :

Fichier vide après une écriture dedans.


Sujet :

C++

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

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : Juin 2008
    Messages : 59
    Points : 43
    Points
    43
    Par défaut Fichier vide après une écriture dedans.
    Bien le bonjour,

    Je fais appel à vous, car je rencontre un petit problème avec les fichiers...

    En fait, j'ouvre un fichier, ensuite, j'essaye d'écrire dedans, mais rien n'y fait, le fichier reste désespérément vide après l'écriture...

    Voici le 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
    int entete = 0;
    fichier.open(nomFichier, ios::in | ios::out || ios::ate);
     
    if(fichier.is_open())
    {
        fichier.close();
    }
    else
    {
        fichier.open(nomFichier, ios::out | ios::app);
     
        if(fichier.is_open())
        {
            fichier.write((char*)&entete, sizeof(entete));
            cout << "test" << endl;
            fichier.close();
        }
    }
    En fait, le premier open sert à vérifier si le fichier existe. En effet, pour que le fichier s'ouvre avec ces options, il doit préalablement exister...

    Ensuite, si il est ouvert, c'est qu'il existe, et je peux le refermer.

    Sinon, je le crée avec le second open, et ensuite, j'y écris un entête (qui représente le nombre d'enregistrements dans le fichier), et je referme le fichier.

    Le problème est que après l'écriture dans le fichier, le "test" du cout est bien affiché, mais le fichier est vide (taille : 0 bytes)...

    Quelqu'un voit où se trouve le problème ?
    Je précise que je travaille sous un système UNIX.

    Merci beaucoup !

  2. #2
    Membre éprouvé
    Avatar de mitkl
    Homme Profil pro
    Étudiant
    Inscrit en
    Février 2010
    Messages
    364
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Février 2010
    Messages : 364
    Points : 1 081
    Points
    1 081
    Par défaut
    Bonjour,

    il a beaucoup plus simple pour enregistrer pour int dans un fichier.

    Je ne comprends pas beaucoup ce que cette ligne est censée faire, cast en char* de l'adresse de entete ? c'est normal que ton fichier est vide :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
            fichier.write((char*)&entete, sizeof(entete));
    mais ça peut être remplacé par

    tout simplement

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

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : Juin 2008
    Messages : 59
    Points : 43
    Points
    43
    Par défaut
    En fait, le casting, c'est imposé par la méthode write()...

    Et, l'écriture se fait en binaire, le "<<" fonctionne aussi dans ce cas ?

    Merci

  4. #4
    Membre éprouvé
    Avatar de mitkl
    Homme Profil pro
    Étudiant
    Inscrit en
    Février 2010
    Messages
    364
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Février 2010
    Messages : 364
    Points : 1 081
    Points
    1 081
    Par défaut
    Alors plusieurs choses :

    - (char*) n'est pas imposé par write(), tu fais juste le forcing en castant &entente en (char*) pour éviter le warning du compilateur, mais caster une adresse en (char*) c'est déjà curieux à la base pour enregistrer un int.

    - l'écriture ne se fait pas en binaire avec ios::app ne signifie pas un enregistrement en binaire, c'est un raccourci d'"append" qui va placer le contenu en fin de fichier.

    - il n'y a aucun problème pour utiliser << int même dans un fichier binaire.

  5. #5
    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
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ios::in | ios::out || ios::ate
    hmm c'est sur qu'avec un ou logique (||) au lieu d'un ou binaire (|) ça risque de moins bien se passer.

    Sinon je ne comprends pas du tout le coup de la double ouverture du fichier une fois avec ate, une fois avec app. Il suffit d'ouvir le fichier une seule fois avec app, si le fichier existe alors les données seront écrit à la fin, si le fichier n'existe pas alors il sera crée.

    Donc pour moi le code devrait se limiter à :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    int entete = 1;
    std::ofstream fichier(nomFichier, std::ios::app);
     
    if(fichier)
    {
       fichier.write((char*)&entete, sizeof(entete));
       std::cout << "test" << std::endl;
       fichier.close();
    }
    @mitkl
    Il n'existe à ma connaissance qu'un seul et unique moyen pour écrire en binaire dans un fichier avec la biblio iostream en C++ et c'est d'utiliser la fonction membre write(const char*, std::streamsize). Si tu fais << int ça écrira en texte.

  6. #6
    Expert confirmé

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2007
    Messages
    1 895
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Septembre 2007
    Messages : 1 895
    Points : 4 551
    Points
    4 551
    Par défaut
    Citation Envoyé par mitkl Voir le message
    - (char*) n'est pas imposé par write(), tu fais juste le forcing en castant &entente en (char*) pour éviter le warning du compilateur, mais caster une adresse en (char*) c'est déjà curieux à la base pour enregistrer un int.
    Un warning ? Allons, allons. Le cast est imposé - il n'y a pas de cast implicite de T* (quelque soit T) vers char* en c++ (et la méthode ::write() prends un const char* en paramètre). Si tu n'as qu'un warning, alors change ton compilateur - parce que soit l'implémentation de la librairie standard est incorrecte, soit le compilateur fait des choses étranges.

    Ensuite, caster en char* dans ce contexte, s'est tout sauf étrange : il s'agit d'enregistrer un flux de caractères - c'est à dire un flux de donnée dont chaque member a une taille de 1 - dans un fichier.

    Citation Envoyé par mitkl Voir le message
    - l'écriture ne se fait pas en binaire avec ios::app ne signifie pas un enregistrement en binaire, c'est un raccourci d'"append" qui va placer le contenu en fin de fichier.

    - il n'y a aucun problème pour utiliser << int même dans un fichier binaire.
    Je pense que l'OP veut dire que << n'écrit pas un int sous sa forme binaire, mais sous la forme d'une chaine, ce que à priori il ne souhaite pas faire.

    Ensuite, pour ostream::write(), cf. http://www.cplusplus.com/reference/o...ostream/write/ ; le code de 'lOP, de ce point de vue, est correct (il stocke les sizeof(entete) bytes à partir de l'adresse &entete).

    @OP : ton code est compliqué à suivre. Je te conseille de l'écrire autrement.

    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
     
    // dans un namespace anonyme - du coup, la fonction
    // n'est visible que dans cette unité de compilation
    namespace {
        inline bool file_exists(const std::string& path)
        {
            // un ifstream est nécessairement ouvert en lecture
            // si l'ouverture échoue, l'objet est quand même créé
            // mais son bit filbit est positionné - on peut donc le
            // récupérer avec la méthode fail()
            std::ifstream  file(path.c_str());
            return !file.fail();
        }
    }
     
    void store_header(const std::string& fpath, const header_type& header)
    {
        if (file_exist(fpath))
            return; 
     
        // le bin est là pour faire joli. Sur Unix, il n'a pas d'effet. 
        // le app est aussi implicite - vu que c'est un ostream, 
        // le app est le fonctionnement par défaut. En fait, on
        // pourrait tout à fait se satisfaire du premier paramètre
        // uniquement. 
        std::ofstream file(fpath.c_str(), std::ios::app|std::ios::binary);
        if (!file)
            return;
     
        file.write(reinterpret_cast<char*>(&header), sizeof(header));
     
        // pas besoin de fermer : le destructeur de file s'en charge très
        // bien. Il fait même le flush avant. 
    }

  7. #7
    Expert confirmé

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2007
    Messages
    1 895
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Septembre 2007
    Messages : 1 895
    Points : 4 551
    Points
    4 551
    Par défaut
    Citation Envoyé par Arzar Voir le message
    Sinon je ne comprends pas du tout le coup de la double ouverture du fichier une fois avec ate, une fois avec app. Il suffit d'ouvir le fichier une seule fois avec app, si le fichier existe alors les données seront écrit à la fin, si le fichier n'existe pas alors il sera crée.
    C'est un test d'existence : si le fichier existe, on écrit pas dedans

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

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : Juin 2008
    Messages : 59
    Points : 43
    Points
    43
    Par défaut
    Bonjour à tous, et merci pour vos réponses.

    Alors, Arzar, le || est une erreur de recopiage de ma part... Je travaille sur une machine virtuelle, donc impossible de copier-coller (je fais mes recherches hors machine virtuelle, car une résolution de 1024x768, c'est pas top pour surfer, et je n'ai pas les compétences nécessaires que pour tenter de paramétrer la machine virtuelle pour l'instant)... J'ai donc bien un | dans mon code.
    La première ouverture est bien un test d'existence.

    Sinon, comme le dis Emmanuel, je ne veux PAS écrire en texte dans mon fichier, mais bien en binaire.
    Ensuite, Emmanuel, je vais tenter d'intégrer ton code ce soir, bien qu'il y ait des notions que je ne connaisse pas dedans. Je chercherai un peu sur le net.

    Je vous tiens au courant

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

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : Juin 2008
    Messages : 59
    Points : 43
    Points
    43
    Par défaut
    C'est bon, problème résolu.

    J'avais en fait mal compris les flux...
    Du coup, dans ma classe, je déclarais le fichier comme fstream.
    J'ai simplement déclaré un ofstream, et un ifstream, et j'ai adapté le code de la méthode pour ouvrir en ifstream quand je veux lire dans le fichier, et en ofstream quand je veux écrire dedans.

    Et ça fonctionne.

    C'est probablement améliorable, mais je me contenterai de cette solution pour l'instant, par manque de temps pour explorer d'autres pistes...

    Merci à tous !

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

Discussions similaires

  1. modifier fichier host après une saisie de l'utilisateur à l'écran
    Par princesse95 dans le forum Programmation et administration système
    Réponses: 5
    Dernier message: 18/11/2009, 09h07
  2. Table toujours vide après une restauration !
    Par agdid04 dans le forum Recovery Manager
    Réponses: 2
    Dernier message: 09/06/2009, 19h50
  3. [ClickOnce] Garder des fichiers modifiés après une update
    Par User.Anonymous dans le forum VB.NET
    Réponses: 1
    Dernier message: 04/06/2009, 17h48
  4. fichier vide après command cp (unix)
    Par leo77 dans le forum C
    Réponses: 6
    Dernier message: 17/04/2009, 15h57
  5. [batch]fichiers modifiés après une certaine date
    Par skalimer0 dans le forum Scripts/Batch
    Réponses: 1
    Dernier message: 10/09/2008, 09h14

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