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 :

Déplacer un pointeur dans un fichier


Sujet :

C++

  1. #1
    Membre régulier
    Homme Profil pro
    Spécialiste en Maintenance Applicative / Developpeur C#, VB, PL-SQL, T-SQL
    Inscrit en
    Septembre 2008
    Messages
    206
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Spécialiste en Maintenance Applicative / Developpeur C#, VB, PL-SQL, T-SQL
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2008
    Messages : 206
    Points : 93
    Points
    93
    Par défaut Déplacer un pointeur dans un fichier
    Bonjour,

    Je réalise une méthode qui doit lire un fichier texte ligne par ligne (jusque la pas de problemes ).
    Le fichier contient plusieures "sections" et chaque section est composé de 27 lignes. Je doit récupérer les 27 lignes d'une section si la premiere ligne (de cette même section) contient la date systeme. Sinon, je passe à la section suivante.

    Je souhaite donc placer le pointeur 27 lignes plus tard. J'ai voulu utiliser la fonction Seek() mais je n'ai pas réussi à l'utiliser dans mon cas.

    Comment faire ?

    Merci.

    Langage : c++ MFC avec la librairie StdioFile

  2. #2
    Rédacteur

    Avatar de ram-0000
    Homme Profil pro
    Consultant en sécurité
    Inscrit en
    Mai 2007
    Messages
    11 517
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Consultant en sécurité
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2007
    Messages : 11 517
    Points : 50 367
    Points
    50 367
    Par défaut
    le fseek() à des contraintes sur les fichiers texte (c'est probablement lié à les gestion du \n de fin de ligne qui peut faire 1 ou 2 caractères suivant les systèmes et les fichiers).

    Je pense que dans ton cas, il est plus sage de lire les 27 lignes suivantes et de les ignorer.

  3. #3
    Membre régulier
    Homme Profil pro
    Spécialiste en Maintenance Applicative / Developpeur C#, VB, PL-SQL, T-SQL
    Inscrit en
    Septembre 2008
    Messages
    206
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Spécialiste en Maintenance Applicative / Developpeur C#, VB, PL-SQL, T-SQL
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2008
    Messages : 206
    Points : 93
    Points
    93
    Par défaut
    Je suis en partie d'accord avec toi. Mais il n'y a pas que la premiere ligne d'une section qui contient une date et mon code est le suivant :

    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
    /* Ouverture du fichier */
    	monfichier->Ouvrir_En_Lecture();
    	CString findepage = "<-----FIN-PAGE----->";
    	int i = 0;
    	monfichier->lire_Fichier();
    	do
    	{
    		if(monfichier->buf.Compare(monfichier->laDate->date) == S_OK)
    		{
    			/* Récupere les dates de diffusion, les découpe en jour, mois et année et
    			 * les envoie à la classe PAGE */
    			mapage->Date_Affichage_debut = monfichier->buf;
    			monfichier->lire_Fichier();
    			mapage->Date_Affichage_fin = monfichier->buf;
    			do
    			{
    				monfichier->lire_Fichier();
    				mapage->contenu = monfichier->buf;
    				monfichier->lire_Fichier();
    				mapage->allign = monfichier->buf;
    				monfichier->lire_Fichier();
    				mapage->cligno = monfichier->buf;
    				mapage->LesLignes[i]->SetAtributs(mapage->contenu, mapage->allign, mapage->cligno);
    				i++;
    			}while(monfichier->buf.Compare(findepage) != S_OK);
    		}
    		else
    		{
    		}
    	}while(monfichier->lire_Fichier != false);
    Et le fichier est comme suit :

    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
    26/04/09
    23/04/09
    Attention
    1
    0
    ce flim
    2
    1
    n'est pas
    1
    0
    un flim
    2
    1
    sur le
    1
    0
    cyclimsme...
    2
    1
    Merci de votre
    1
    0
    compréhension
    2
    1
    <-----FIN-PAGE----->
    Comme on peut le voir dans mon code, je test si la ligne courante contient la date systeme. Hors, vu que la deuxieme ligne contient aussi une date, il faut absolument que je passe à la section suivante si la premiere ligne en correspond pas.

    J'espere que je suis clair dans mes explications... c'est pas toujours facile !!!

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 626
    Points : 30 684
    Points
    30 684
    Par défaut
    Salut,

    Peut être devrais tu envisager de manipuler ton fichier sous la forme ISAM...

    En effet, si tu ne peux pas avoir la certitude que toutes tes sections ou tes lignes représentent un nombre clairement défini de bytes, tu n'as que deux solutions:

    La première consiste à t'arranger pour lire sans interpréter les 26 lignes inutiles, ce qui t'oblige à chaque fois à ... lire l'ensemble des sections qui précèdent celle qui t'intéresse, qui ne pose peut être pas de problème si le fichier ne contient que quelques sections, mais qui peut rapidement représenter une perte de temps énorme si tu dois accéder à la 100eme, à la 1000 ou à la 1.000.000eme section

    La deuxième consiste à t'arranger pour disposer "quelque part" de "jalons" te permettant de retrouver certaines informations dans le fichier.

    En effet, un fichier n'est jamais, si on le regarde du point de vue le plus bas niveau possible, qu'une suite finie de bytes qui prennent la signification propre à leur position dans la suite.

    Comme toute suite finie, un fichier est - fatalement - caractérisé par un début et une fin, et, comme tout élément de suite, il est possible de caractériser chacun des byte du fichier par... la position qu'il occupe à l'intérieur du fichier (son "index").

    L'idée est de garder quelque part l'index (et, pour être précis, dans un autre fichier, dont nous choisirions arbitrairement de donner l'extension idx (pour InDex) ) de certaines informations qui nous intéressent, dans le cas, l'index du premier caractère de chaque section.

    Cet index peut, au choix, être chargé "à la demande", voire, être considéré comme un fichier écrit en "mode binaire" (même si le terme n'est pas vraiment approprié), et lu "à la volée" en allant directement "chercher le Nième index".

    de cette manière, une "simple" règle mathématique te permet, sur base de l'adresse du départ du fichier, d'accéder en temps constant à n'importe quelle section de ton fichier

    Ce principe, énoncé simplement et donc de manière forcément incomplète et potentiellement pas tout à fait juste, pose les jalon d'un accès aux fichiers que l'on appelle ISAM (Indexed Sequential Access Method).

    L'avantage de ce principe, c'est que ce n'est absolument pas intrusif par rapport au fichier d'origine (celui qui contient effectivement les données intéressantes) :

    Si, même, le fichier d'origine contient déjà une quantité importante de données, il est malgré tout facile (quoi que potentiellement gourmand en temps) de le relire complètement et de créer l'index sur base des données lues

    De même, en cas d'ajout de données, il est très facile d'en profiter pour rajouter l'index à la volée, ce qui ne demande que très peu de temps, étant donné qu'il "suffit" d'ouvrir le fichier d'index en ajout, et d'y écrire l'index de la nouvelle section.

    Enfin, l'existence du fichier d'index n'oblige malgré tout pas à son utilisation: si tu dispose déjà d'applications qui se contentent de lire l'ensemble du fichier pour obtenir les informations intéressantes, tu n'est absolument pas obligé de les modifier.

    L'inconvénient, c'est que tu devra par contre modifier les applications, s'il y en a plusieurs, qui font les ajouts dans le fichier de manière à garder l'index cohérent (il serait moche d'avoir trois applications qui tiennent le fichier d'index à jour et trois autres qui ne le font pas )

    Et, bien sur, cela "complexifie" un peu la logique de lecture si tu souhaite mettre en place:
    Au lieu de te contenter de lectures en boucle, tu dois envisager une logique proche de
    1. chercher l'index
    2. sauter à l'index indiqué dans le fichier de données
    3. effectuer la lecture
    4. le cas échéans, recommencer en 1


    La logique d'écriture pourrait être proche de
    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
    void ecriture(std::string f, DATA const & d)
    {
        /* !!! filename représente le nom de fichier SANS EXTENSION 
         * DATA représente le type de données à écrire
         */
        std::string data = f+".txt"; /* le nom du fichier de données */
        std::string index = f+".idx"; /* le nom du fichier d'index */
        /* l'ouverture des fichier d'index et de données, 
         * nous allons directement à la fin des fichiers 
         */
        std::ofstream idx(index.c_str(),std::ios_base::binary|std::ios_base::app);
        std::ofstream dat(data.c_str(),std::ios_base::app);
        /* il nous faut la position de fin du fichier de donnée, qui correspond
         * à l'index que prendra le début de l'information qui
         */
        long size=dat.tellg();
        /* écrivons cette position dans le fichier d'index */
        idx.write(reinterpret_cast<const char*>(&value), sizeof(long));
        /* et écrivons les données dans le fichier adéquat */
        dat<<d.truc()<<std::endl
           <<d.brol()<<std::endl
           <<d.bidule<<std::endl;
    }
    NOTA: L'utilisation d'un fichier de type binaire pour l'index est la solution la plus rapide et la moins gourmande en mémoire, mais elle peut présenter des problèmes si tes données doivent être gérées sur différentes architectures, du fait des différences éventuelles de boutisme et / ou de taille du type long

    La lecture d'une donnée particulière, basée sur son index, pourrait être proche de
    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
    void lecture(std::string f, DATA& d, size_t ind)
    {
        /* comme pour l'écriture, f ne représente que le nom SANS EXTENTION
         * du fichier, nous avons donc besoin de créer les noms avec 
         */
        std::string data = f+".txt"; /* le nom du fichier de données */
        std::string index = f+".idx"; /* le nom du fichier d'index */
        /* nous aurons besoin de l'index dans le fichier de données */
        long real;
        /* ouvrons le fichier d'index, et positionnons nous sur l'index qui
         * nous intéresse, et lisons le
         */
        {
            /* Ce bloc d'instructions permet que le fichier index soit
             * refermé dés la lecture effectuée (merci RAII)
             */ 
            std::ifstream idx(index.c_str(),std::ios_base::binary);
            idx.fseek(0, ind*size_of(long));
            idx.read(reinterpret_cast<char*>(&value), sizeof(long));
        }  
        /* ouvrons le fichier de données, plaçons nous au bon endroit, 
         * et lisons les informations qui nous intéressent
         */
        std::ifstream dat(data.c_str());
        dat.fseek(0,real);
        /*lecture des données de manière classique */
    }
    Une solution plus portable, mais également plus gourmande en ressources, consiste à créer le fichier d'index sous la forme d'un simple fichier texte, ce qui pourrait transformer la fonction d'écriture en

    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
    void ecriture(std::string f, DATA const & d)
    {
        /* !!! freprésente le nom de fichier SANS EXTENSION 
         * DATA représente le type de données à écrire
         */
        std::string data = f+".txt"; /* le nom du fichier de données */
        std::string index = f+".idx"; /* le nom du fichier d'index */
        /* l'ouverture des fichier d'index et de données, 
         * nous allons directement à la fin des fichiers 
         */
        std::ofstream idx(index.c_str(), std::ios_base::app);
        std::ofstream dat(data.c_str(), std::ios_base::app);
        /* il nous faut la position de fin du fichier de donnée, qui correspond
         * à l'index que prendra le début de l'information qui
         */
        long size=dat.tellg();
        /* écrivons cette position dans le fichier d'index */
        idx<<size<<" "; /* nous pourrions remplacer " " par std::endl ;) */
        /* et écrivons les données dans le fichier adéquat */
        dat<<d.truc()<<std::endl
           <<d.brol()<<std::endl
           <<d.bidule<<std::endl;
    }
    Nous commencerions alors par charger l'intégralité de l'index dans un vecteur, sous la forme de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    void initIndex(std::string const& fstd::vector<long>& v)
    {
        /* !!! freprésente le nom de fichier SANS EXTENSION */
        std::string index=f+".idx";
        long id;
        std::fstream idx(index.c_str());
        while((idx>>id))
            v.push_back(id);
    }
    et la lecture de l'information qui nous intéresse prendrait la forme de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    void lecture(long offset, std::string const& f, DATA &)
    {
        /* !!! freprésente le nom de fichier SANS EXTENSION 
         * offset représente la position du début de l'information
         * qui nous intéresse
         */
        std::string data = f+".txt"; /* le nom du fichier de données */
       std::ifstream dat(data.c_str());
       dat.fseek(0,offset);
       /*lecture des informations */
     
    }
    Le tout serait géré sous une forme proche de
    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
    int main()
    {
        /* le  vecteur reprenant les indexes */
        std::vector<long> indexes;
        /* le nom du fichier SANS EXTENSION */
        std::string filename("mes_donnees");
        /* chargement de l'index */
        initIndex(filename,indexes);
        /* la donnée qui  va être lue */
        DATA dat;
        /* récupération de la troisième donnée 
         * !!! ne pas oublier que l'index dela première donnée se trouve en v[0]
         */
        lecture(v[2],filename,dat);
        /*...*/
        return 0;
    }
    Conclusion: tous les codes sont écrits "from scratch", et aucun n'a été testé...: ils ont comme seul objectif de présenter la manière de s'y prendre, et les commentaires rajoutés devraient te permettre de comprendre ce sur quoi je suis passé peut être trop vite

    *Normalement*, ils sont exempts d'erreurs, mais... l'erreur est humaine, et je n'ai pas la prétention d'être meilleur que les autres

    Certaines vérifications supplémentaires peuvent être ajoutées, afin de sécuriser les différentes lectures / écritures.

  5. #5
    Membre régulier
    Homme Profil pro
    Spécialiste en Maintenance Applicative / Developpeur C#, VB, PL-SQL, T-SQL
    Inscrit en
    Septembre 2008
    Messages
    206
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Spécialiste en Maintenance Applicative / Developpeur C#, VB, PL-SQL, T-SQL
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2008
    Messages : 206
    Points : 93
    Points
    93
    Par défaut
    Merci beaucoup pour cette reponse mais malheureusement je n'ai pas le temps de mettre ça en oeuvre. La méthode que je réalise est juste une infime partie d'une programme de gestion d'afficheur cinéma à led. Et comme tu l'a dit il faudrai modifier l'écriture du fichier (dont je ne me suis pas aucupé). Mais c'est néanmoins tres intéressant, j'ai apris pas mal de truc, je vai mettre ça de coté pour une prochaine fois.

    Je vais donc "pour lire sans interpréter les 26 lignes inutiles". Mon fichier ne contiendra jamais 1.000.000 sections. Il n'est meme pas sur qu'il en contienne plus de 50 !!! Le fichier est éffacé et recréé chaque mois, j'ai donc rien à craindre niveau performance de l'application.

    Merci à vous deux, ça m'a permis d'avancer

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 626
    Points : 30 684
    Points
    30 684
    Par défaut
    Attention, je n'ai peut être pas été bien clair au sujet de l'écriture...

    L'idéal est, effectivement, que toute écriture dans le fichier de données implique l'ajout de l'index équivalent dans le fichier d'index...

    Mais, même si l'écriture des données est déjà fonctionnelle, il reste malgré tout très simple d'envisager de "recréer" (ou de modifier) le fichier d'index de manière externe.

    Rien ne t'empêche en effet de prévoir une application qui se chargera soit de recréer le fichier d'index, en parcourant tout le fichier de données et en recréant tout le fichier, soit de le compléter en se basant sur le fichier d'index pour ne rajouter que les entrées supplémentaires.

    Cette application pourrait, au choix, être appelée:
    • à la demande (par script ou autre)
    • juste avant de quitter l'application qui manipule le fichier de données en écriture
    • comme première instruction de l'application qui manipule les données en lecture
    (plusieurs choix possibles)

    En effet, la seule obligation par rapport au fichier d'index, c'est qu'il soit à jour si tu décide de l'utiliser... le moment où s'effectue la mise à jour n'ayant, en définitive, que peu d'importance

    C'est l'énorme avantage qu'il y a à la gestion d'un fichier d'index séparé (car il serait aussi possible (mais plus compliqué à mettre en oeuvre) d'avoir l'index en début de fichier): il n'est absolument pas invasif, et il ne sert que... si tu décide de l'utiliser

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

Discussions similaires

  1. Déplacer un noeud dans un fichier xml
    Par cricri77200 dans le forum XML/XSL et SOAP
    Réponses: 1
    Dernier message: 03/06/2010, 12h14
  2. Déplacer une ligne de code dans un fichier XML ?
    Par Papy Octet dans le forum Interfaçage autre langage
    Réponses: 2
    Dernier message: 11/03/2010, 08h17
  3. Réponses: 2
    Dernier message: 08/02/2008, 11h03
  4. double pointeur dans un fichier txt
    Par micka180 dans le forum VBScript
    Réponses: 14
    Dernier message: 22/01/2008, 16h23
  5. [Forms - PL/SQL] Se déplacer dans un fichier
    Par Yoshidu62 dans le forum Forms
    Réponses: 2
    Dernier message: 15/11/2007, 11h21

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