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

Langage C++ Discussion :

Ouverture de fichier avec ofstream en écriture exclusive ???


Sujet :

Langage C++

  1. #1
    Futur Membre du Club
    Inscrit en
    Juin 2008
    Messages
    37
    Détails du profil
    Informations forums :
    Inscription : Juin 2008
    Messages : 37
    Points : 7
    Points
    7
    Par défaut Ouverture de fichier avec ofstream en écriture exclusive ???
    Bonsoir à tous,

    Mon appli écrit dans un fichier grâce à des ofstream et flux ( monFichier << "titi" << endl; ).
    J'ouvre le fichier avec notepad pendant que mon appli écrit dedans. Je ferme notepad puis réouvre ce même fichier, je vois alors les nouvelles écritures faites par mon appli pendant que je lisais le fichier.
    Mon problème est que lorsque je l'ouvre avec Excel par exemple, cela bloque les écritures de mon appli, et plus aucune écriture n'est ajoutée dans ce fichier par mon appli (sauf si je la redémarre). Je suppose qu'Excel modifie les permissions...

    J'ai trouvé dans la MSDN le prototype de , qui en 3ème paramètre attend un droit d'accès.
    http://msdn.microsoft.com/en-us/libr...hc(VS.80).aspx
    C'est ce droit qui m'intéresse car je souhaite interdire Excel d'empêcher mon appli d'écrire dans ce fichier !!!
    Or sous Visual 6 apparemment, le droit filebuf::sh_read existait mais a disparu sous Visual 2005... !

    Savez-vous comment puis-je faire pour interdire les autres applications à bloquer l'accès à mon fichier lorsque j'écris dedans ?

    Merci d'avance

    N.B. : Le plus étonnant est que lorsque j'ouvre le fichier avec Excel, il me demande si je veux l'ouvrir en lecture seule et je lui réponds OUI ! Donc pourquoi me bloque-t-il l'accès ???



    Actuellement, j'ouvre mon fichier de la façon suivante :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    ofstream monFichier;
    monFichier.open("C:\\toto.xls", ios_base::app);
    monFichier << "titi" << endl;

  2. #2
    Futur Membre du Club
    Inscrit en
    Juin 2008
    Messages
    37
    Détails du profil
    Informations forums :
    Inscription : Juin 2008
    Messages : 37
    Points : 7
    Points
    7
    Par défaut
    J'ai trouvé la constante _SH_SECURE qui est définie dans le même fichier que la valeur du paramètre par défaut _OpenProt de la méthode open(), mais lorsque je mets cette constante, c'est pareil.

    A priori on ne peut pas utiliser ce fameux 3ème argument :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    void open(
        const wchar_t *_Filename,
        ios_base::openmode _Mode = ios_base::out,
        int _Prot = (int)ios_base::_Openprot
    );

  3. #3
    Expert éminent
    Avatar de Melem
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Janvier 2006
    Messages
    3 656
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Janvier 2006
    Messages : 3 656
    Points : 8 389
    Points
    8 389
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    #include <share.h>
    ...
    file.open(filename, mode, _SH_DENYRW);

  4. #4
    Futur Membre du Club
    Inscrit en
    Juin 2008
    Messages
    37
    Détails du profil
    Informations forums :
    Inscription : Juin 2008
    Messages : 37
    Points : 7
    Points
    7
    Par défaut
    Merci, mais j'ai essayé _SH_SECURE et _SH_DENYW, ça n'a rien changé. J'essaierai tout de même demain _SH_DENYRW mais à priori c'est pour Read + Write et je ne veux bloquer que l'écriture (_SH_SECURE a l'air pas mal mais Excel à l'air aussi de s'en moquer... ?)

  5. #5
    Futur Membre du Club
    Inscrit en
    Juin 2008
    Messages
    37
    Détails du profil
    Informations forums :
    Inscription : Juin 2008
    Messages : 37
    Points : 7
    Points
    7
    Par défaut
    Je confirme que ça n'a pas résolu mon problème. Excel me bloque toujours l'écriture dans mon fichier...

  6. #6
    Expert éminent
    Avatar de Melem
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Janvier 2006
    Messages
    3 656
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Janvier 2006
    Messages : 3 656
    Points : 8 389
    Points
    8 389
    Par défaut
    Tu sais, puisque t'es déjà résolu à utiliser des extensions non standard, et que tu bosses définitivement sous Windows, pourquoi n'utilise pas tu directement CreateFile et co. ? Ça t'évitera bien des problèmes.

    En tout cas, c'est toujours celui qui a ouvert le fichier en premier qui fixe les règles. Si tu as ouvert le fichier en premier mais que tu autorise les autres programmes à faire ce qu'ils veulent du fichier, le deuxième programme qui ouvre le fichier sera alors à son tour le maître, et ainsi de suite. Dès qu'un programme dit que les autres programmes n'ont pas le droit de faire ceci ou faire cela sur tel fichier, et que Windows a accepté sa demande, les autres programmes doivent attendre leur tour.

    Pour ouvrir un fichier en mode exclusif (si tu en as le droit), c'est :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    HANDLE hFile = CreateFile(
        FileName,
        GENERIC_READ | GENERIC_WRITE,
        0, // Share
        NULL, // Security Attributes
        OPEN_EXISTING, // Le fichier doit déjà exister
        0, // Flags additionnels, optionnels
        NULL // HANDLE d'un fichier à utiliser comme modèle
    );
    Utilise ReadFile pour lire dans le fichier, WriteFile pour écrire et CloseFile pour le fermer.

  7. #7
    Futur Membre du Club
    Inscrit en
    Juin 2008
    Messages
    37
    Détails du profil
    Informations forums :
    Inscription : Juin 2008
    Messages : 37
    Points : 7
    Points
    7
    Par défaut
    J'ai en effet essayé la méthode CreateFile en attendant une réponse sur le forum.
    Rien ne changeait...

    Je trouver pourquoi :
    Je boucle sur fileHandle = CreateFile(nomFichier, ..., OPEN_ALWAYS, ...); car je veux que mon appli me crée un nouveau fichier si l'on change de jour (et je mets nomFichier à jour avec une nouvelle date...).
    Or le handle est écrasé à chaque fois... donc l'appli en crée un nouveau sans fermer l'ancien, elle se bloque elle-même.
    Pour résoudre le problème j'effectue donc un test pour vérifier si le fichier existe et ne fermer et recréer le handle que si nécessaire...

    Donc, ça fonctionne maintenant et je vous en remercie beaucoup !

    Il me reste une chose à résoudre... pourquoi ça ne fonctionnait pas avec mon file.open() ? Je me demande si ce n'était pas le même type de problème. Je vérifie et vous tiens au courant !

  8. #8
    Futur Membre du Club
    Inscrit en
    Juin 2008
    Messages
    37
    Détails du profil
    Informations forums :
    Inscription : Juin 2008
    Messages : 37
    Points : 7
    Points
    7
    Par défaut
    Je ne suis pas allé beaucoup plus loin, je ne sais pas trop pourquoi ça ne fonctionnait pas avec ofstream, mais en tout cas ça fonctionne avec CreateFile et les bons flags (et les méthodes LockFile, SetFilePointer(...FILE_END), WriteFile et UnlockFile).

    Encore merci .

    Bonne soirée.

  9. #9
    Futur Membre du Club
    Inscrit en
    Juin 2008
    Messages
    37
    Détails du profil
    Informations forums :
    Inscription : Juin 2008
    Messages : 37
    Points : 7
    Points
    7
    Par défaut
    Bonjour,

    Je reviens juste apporter quelques précisions.
    En poussant un peu plus mes tests je me suis rendu compte que pour un gros flot de données, certaines lignes n'étaient pas écrites lorsque j'ouvrais plusieurs fois le fichier avec Excel (je pense que ça devait être pareil avec d'autres applications, hormis notepad, mais pas testé...).

    J'ai donc réessayer avec ofstream + flag SH_SECURE ou SH_DENYWR, mais aussi avec les fonctions classiques fopen_s, fputs, etc.

    J'ai fini par comprendre l'origine du problème. Il faut utiliser LockFileEx et UnlockFileEx pour bloquer la zone du fichier où l'application va écrire. Mais les méthodes LockFile et UnlockFile par contre ne suffisaient pas car lorsque j'ouvrais Excel, elles ne pouvaient pas bloquer cette zone à écrire !!! D'où l'utilisation de LockFileEx sans le flag LOCKFILE_FAIL_IMMEDIATELY !

    Documentation :
    http://msdn.microsoft.com/en-us/libr...02(VS.85).aspx
    http://msdn.microsoft.com/en-us/libr...03(VS.85).aspx

    Exemple :

    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
     
    /**
    * @brief Ecrit une ligne dans le fichier, en gerant l'acces exclusif au fichier.
    * 
    * Methode qui ecrit le message passe en parametre, dans le fichier, en bloquant
    * de facon exclusive la zone du fichier a ecrire pour eviter qu'une tierce application
    * ne la bloque pour elle (attente qu'elle soit debloquee le cas echeant).
    * 
    * @param ligne a ecrire dans le fichier.
    */
    void Fichier::ecrireLigne(string p_message)
    {
    	// Nombre d'octets a ecrire
    	m_nbCar = (DWORD)strlen(p_message.c_str())*sizeof(char);
     
    	// Preparation de la structure OVERLAPPED pour ecrire en fin de fichier
    	m_over.hEvent = 0;
    	m_over.Offset = SetFilePointer(m_fileHandle, 0, NULL, FILE_END);
    	m_over.OffsetHigh = 0;
     
    	// On bloque la zone a ecrire, de facon exclusive, pour eviter que l'ouverture du fichier par une tierce application n'empeche d'ecrire a cet emplacement.
    	// On utilise LockFileEx plutot que LockFile pour eviter que l'ouverture du fichier par une tierce application n'empeche de bloquer la zone.
    	// LockFileEx permet en effet d'attendre que cette zone soit debloquee pour la reserver.
    	LockFileEx(m_fileHandle, LOCKFILE_EXCLUSIVE_LOCK, 0, m_nbCar, 0, &m_over);
     
    	// Ecriture de la ligne dans la zone reservee
    	WriteFile(m_fileHandle, p_message.c_str(), m_nbCar, &m_nbLus, NULL);
     
    	// Deblocage de la zone reservee
    	UnlockFileEx(m_fileHandle, 0, m_nbCar, 0, &m_over);
    }
    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
     
    HANDLE m_fileHandle;
    OVERLAPPED m_over;
    DWORD m_nbCar;
    DWORD m_nbLus;
    // etc. J'en ai peut-etre oublié...
     
    m_fileHandle=CreateFile(m_nomFichier.c_str(), GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
    if(m_fileHandle == INVALID_HANDLE_VALUE)
    {
    	// Traitement de l'erreur...
    }
     
    string maLigneAEcrire = "Ligne a ecrire numero ";
     
    for(int i=0 ; i<10 ; i++)
    {
    	maLigneAEcrire << i << endl;
    	ecrireLigne(maLigneAEcrire);
    }
     
    // Fermeture du handle sur le fichier
    CloseHandle(m_fileHandle);

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

Discussions similaires

  1. Réponses: 4
    Dernier message: 27/08/2009, 00h22
  2. Réponses: 15
    Dernier message: 23/06/2006, 13h09
  3. Ouverture de fichier avec un string
    Par slate dans le forum C++
    Réponses: 4
    Dernier message: 17/02/2006, 16h16
  4. ouverture de fichier avec evc4.0
    Par gids01 dans le forum MFC
    Réponses: 4
    Dernier message: 22/11/2005, 13h09
  5. Aide sur ouverture de fichier avec access
    Par FusionR dans le forum PostgreSQL
    Réponses: 1
    Dernier message: 17/06/2004, 12h02

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