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

Contribuez Pascal Discussion :

Opérations sur un fichier d'enregistrements


Sujet :

Contribuez Pascal

  1. #1
    Rédacteur/Modérateur

    Avatar de Roland Chastain
    Homme Profil pro
    Enseignant
    Inscrit en
    Décembre 2011
    Messages
    4 072
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Décembre 2011
    Messages : 4 072
    Points : 15 462
    Points
    15 462
    Billets dans le blog
    9
    Par défaut Opérations sur un fichier d'enregistrements
    Constatant qu'il y a encore fréquemment des questions dans le forum sur les fichiers d'enregistrements, je me suis amusé à écrire un court exemple contenant tout ce qu'il faut savoir sur le sujet (cela dit sans prétention car il n'y a en fait que peu de choses à savoir). Voici donc cet exemple.

    Il y a quelque temps j'avais entrepris de relire tout Pascal () et de relever les phrases que je voulais retenir pour pouvoir les citer avec exactitude. J'ai copié ces phrases au fur et à mesure dans des fichiers faits tous de la même façon, à savoir des fichiers de quatre lignes contenant respectivement la citation, l'œuvre dont elle est tirée, la page et une liste de mots-clés :

    Ainsi, il n'a rien d'extravagant dans sa conduite; il agit comme les autres; et tout ce qu'ils font dans la sotte pensée qu'ils suivent le vrai bien, il le fait par un autre principe, qui est que les vraisemblances étant pareilles d'un et d'autre côté, l'exemple et la commodité sont les contrepoids qui l'entraînent.
    Entretien avec M. de Saci
    570
    Montaigne,extravagance,conduite,exemple
    À partir de cette collection de fichiers, je vais constituer une base de données, sous la forme d'un fichier d'enregistrements.

    Pour ce faire je commence par déclarer le nom du fichier dans une constante, et le type du fichier :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    const
      FICHIER = 'citations.dat';
     
    type
      TCitation = record
        texte: array[0..999] of char;
        opus: shortstring;
        page: word;
        clefs: shortstring;
      end;
     
      TFichierCitations = file of TCitation;
    Ensuite j'écris les différentes procédures dont j'aurai besoin. Premièrement, une procédure pour ajouter un enregistrement :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    procedure Ajouter(const c: TCitation);
    var
      f: TFichierCitations;
    begin
      AssignFile(f, FICHIER);
      if FileExists(FICHIER) then
        Reset(f)
      else
        Rewrite(f);
      Seek(f, FileSize(f));
      Write(f, c);
      CloseFile(f);
    end;
    Je préfère déclarer le fichier comme variable locale, et l'ouvrir et le fermer à l'intérieur de chaque procédure, plutôt que de l'ouvrir dans une procédure, le lire dans une autre, le fermer dans une troisième... Mais ça peut se discuter.

    Ensuite j'ai besoin d'une procédure pour lire le fichier :

    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
    procedure LireTout();
    var
      f: TFichierCitations;
      c: TCitation;
    begin
      if FileExists(FICHIER) then
      begin
        AssignFile(f, FICHIER);
        Reset(f);
        while not EOF(f) do
        begin
          Write(Format('%0.3d ', [FilePos(f)]));
          Read(f, c);
          WriteLn(c.clefs);
        end;
        CloseFile(f);
      end;
    end;
    Et d'une autre pour supprimer un enregistrement à partir de son emplacement :

    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
    procedure Supprimer(const aIndex: longword);
    var
      f: TFichierCitations;
      c: TCitation;
    begin
      if FileExists(FICHIER) then
      begin
        AssignFile(f, FICHIER);
        Reset(f);
     
        // Se placer sur le dernier enregistrement
        Seek(f, FileSize(f) - 1);
        // Le lire
        Read(f, c);
        // Se placer sur l'enregistrement à supprimer
        Seek(f, aIndex - 1);
        // Écrire les valeurs lues précédemment
        Write(f, c);
        // Se replacer sur le dernier enregistrement
        Seek(f, FileSize(f) - 1);
        // Tronquer le fichier
        Truncate(f);
     
        CloseFile(f);
      end;
    end;
    Enfin, une procédure de recherche à partir d'un mot-clé :

    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
    procedure Chercher(const aClef: string);
    var
      f: TFichierCitations;
      c: TCitation;
    begin
      WriteLn(UpperCase(aClef));
      if FileExists(FICHIER) then
      begin
        AssignFile(f, FICHIER);
        Reset(f);
        while not EOF(f) do
        begin
          Read(f, c);
          if Pos(aClef, c.clefs) > 0 then
            WriteLn('  ', c.texte);
        end;
        CloseFile(f);
      end;
    end;
    Cette procédure sera appelée ainsi :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
      Chercher('religion');
      Chercher('Montaigne');
      Chercher('pensée');
      Chercher('homme');
    Ce qui donne le résultat suivant :

    RELIGION
    J'aurais bien plus de peur de me tromper, et de trouver que la religion chrétienne soit vraie, que non pas de me tromper en la croyant vraie.
    MONTAIGNE
    Ainsi, il n'a rien d'extravagant dans sa conduite; il agit comme les autres; et tout ce qu'ils font dans la sotte pensée qu'ils suivent le vrai bien, il le fait par un autre principe, qui est que les vraisemblances étant pareilles d'un et d'autre côté, l'exemple et la commodité sont les contrepoids qui l'entraînent.
    Il inspire une nonchalance du salut, sans crainte et sans repentir. Son livre n'étant pas fait pour porter à la piété, il n'y était pas obligé : mais on est toujours obligé de n'en point détourner. On peut excuser ses sentiments un peu libres et voluptueux en quelques rencontres de la vie; mais on ne peut excuser ses sentiments tout païens sur la mort; car il faut renoncer à toute piété, si on ne veut au moins mourir chrétiennement : or, il ne pense qu'à mourir lâchement et mollement par tout son livre.
    Il me semble que la source des erreurs de ces deux sectes est de n'avoir pas su que l'état de l'homme à présent diffère de celui de sa création; de sorte que l'un remarquant quelques traces de sa première grandeur, et ignorant sa corruption, a traité la nature comme saine et sans besoin de réparateur, ce qui le mène au comble de la superbe; au lieu que l'autre, éprouvant la misère présente et ignorant la première dignité, traite la nature comme nécessairement infirme et irréparable, ce qui le précipite dans le désespoir d'arriver à un véritable bien, et de là dans une extrême lâcheté.
    PENS?E
    En écrivant ma pensée, elle m'échappe quelquefois; mais cela me fait me souvenir de ma faiblesse, que j'oublie à toute heure; ce qui m'instruit autant que ma pensée oubliée, car je ne tends qu'à connaître mon néant.
    Pensée fait la grandeur de l'homme.
    Je puis bien concevoir un homme sans mains, pieds, tête (car ce n'est que l'expérience qui nous apprend que la tête est plus nécessaire que les pieds). mais je ne puis concevoir l'homme sans pensée : ce serait une pierre ou une brute.
    Toute la dignité de l'homme est en la pensée. Mais qu'est-ce que cette pensée ? Qu'elle est sotte !
    L'homme n'est qu'un roseau, le plus faible de la nature; mais c'est un roseau pensant. Il ne faut pas que l'univers entier s'arme pour l'écraser : une vapeur, une goutte d'eau, suffit à le tuer. Mais, quand l'univers l'écraserait, l'homme serait encore plus noble que ce qui le tue, puisqu'il sait qu'il meurt, et l'avantage que l'univers a sur lui, l'univers n'en sait rien.
    HOMME
    Les hommes s'occupent à suivre une balle et un lièvre; c'est le plaisir même des rois.
    Pensée fait la grandeur de l'homme.
    Je puis bien concevoir un homme sans mains, pieds, tête (car ce n'est que l'expérience qui nous apprend que la tête est plus nécessaire que les pieds). mais je ne puis concevoir l'homme sans pensée : ce serait une pierre ou une brute.
    Toute la dignité de l'homme est en la pensée. Mais qu'est-ce que cette pensée ? Qu'elle est sotte !
    L'homme n'est qu'un roseau, le plus faible de la nature; mais c'est un roseau pensant. Il ne faut pas que l'univers entier s'arme pour l'écraser : une vapeur, une goutte d'eau, suffit à le tuer. Mais, quand l'univers l'écraserait, l'homme serait encore plus noble que ce qui le tue, puisqu'il sait qu'il meurt, et l'avantage que l'univers a sur lui, l'univers n'en sait rien.
    Qu'en pensez-vous ?
    Fichiers attachés Fichiers attachés
    Mon site personnel consacré à MSEide+MSEgui : msegui.net

  2. #2
    Responsable Pascal, Lazarus et Assembleur


    Avatar de Alcatîz
    Homme Profil pro
    Ressources humaines
    Inscrit en
    Mars 2003
    Messages
    7 937
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 57
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ressources humaines
    Secteur : Service public

    Informations forums :
    Inscription : Mars 2003
    Messages : 7 937
    Points : 59 415
    Points
    59 415
    Billets dans le blog
    2
    Par défaut
    Bonjour,

    Voici un petit exemple utilisant des enregistrements de taille variable. Cette technique permet d'optimiser la taille du fichier, puisque les chaînes de caractères sont stockées sans perte d'espace. J'ai repris l'exemple d'un fichier de citations, avec des enregistrements similaires à ceux définis par Roland, dont voici les champs :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
        Texte : pChar;
        Opus : pChar;
        Page : Word;
        Clefs : pChar;
    Dans le fichier, les chaînes Texte, Opus et Clefs sont précédées de leur taille, tandis que le champ Page est stocké tel quel. La structure du fichier est donc :
    • 1er enregistrement :
      • Taille du champ Texte (un entier long)
      • Champ Texte
      • Taille du champ Opus (un entier long)
      • Champ Opus
      • Page (un Word)
      • Taille du champ Clefs (un entier long)
      • Champ Clefs
    • 2e enregistrement :
      • Taille du champ Texte (un entier long)
      • Champ Texte
      • Taille du champ Opus (un entier long)
      • Champ Opus
      • Page (un Word)
      • Taille du champ Clefs (un entier long)
      • Champ Clefs
    • ...etc
    Astuce : le nombre d'enregistrements est stocké au tout début du fichier.

    Pendant la durée du programme, les citations sont stockées en mémoire dans une liste chaînée.
    Voici la procédure de sauvegarde du fichier :
    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
    Procedure SauvegardeCitations (var TeteListe, QueueListe : PCitation);
    (* Sauvegarde des citations dans un fichier d'enregistrements de taille variable *)
    Var
      Citation : PCitation;
      Fichier : TFileStream;
      Taille : LongInt;   (* Taille du champ qui suit *)
    Begin
      Citation := TeteListe;
      try
        Fichier := TFileStream.Create(NomFichier,fmCreate);
        (* Sauvegarde du nombre d'enregistrements *)
        Fichier.Write(QueueListe^.Index,SizeOf(QueueListe^.Index));
        (* Sauvegarde des citations *)
        while (Citation <> Nil) do
          begin
            with Citation^ do
              begin
                Taille := StrLen(Texte);
                Fichier.Write(Taille,SizeOf(Taille));
                Fichier.Write(Texte[0],Taille);
                Taille := StrLen(Opus);
                Fichier.Write(Taille,SizeOf(Taille));
                Fichier.Write(Opus[0],Taille);
                Fichier.Write(Page,SizeOf(Page));
                Taille := StrLen(Clefs);
                Fichier.Write(Taille,SizeOf(Taille));
                Fichier.Write(Clefs[0],Taille);
              end;
            Citation := Citation^.pSuiv;
          end;
        Fichier.Free;
      except
        WriteLn('*** Erreur lors de la sauvegarde du fichier ! ***');
      end;
    End;
    Et la procédure de lecture du fichier :
    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
    Procedure ChargementCitations (var TeteListe, QueueListe : PCitation);
    (* Chargement des citations depuis un fichier d'enregistrements de taille variable *)
    Var
      NouvelleCitation : PCitation;
      Fichier : TFileStream;
      Buffer : Array [0..999] of Char;   (* Buffer de lecture de chaîne *)
      Compteur : LongInt;                (* Compteur d'enregistrements *)
      NbEnregistrements : LongInt;       (* Nombre d'enregistrements dans le fichier *)
      Taille : LongInt;                  (* Taille du champ qui suit *)
    Begin
      try
        Fichier := TFileStream.Create(NomFichier,fmOpenRead);
        (* Lecture du nombre d'enregistrements *)
        Fichier.Read(NbEnregistrements,SizeOf(NbEnregistrements));
        (* Lecture des citations *)
        Compteur := 1;
        while (Compteur <= NbEnregistrements) do
          begin
            (* Création d'un nouvel élément zéroté *)
            New(NouvelleCitation);
            FillChar(NouvelleCitation^,SizeOf(NouvelleCitation^),0);
            NouvelleCitation^.Index := 1;
            (* Remplissage des champs *)
            Fichier.Read(Taille,SizeOf(Taille));
            Fichier.Read(Buffer,Taille);
            NouvelleCitation^.Texte := StrNew(Buffer);
            Fichier.Read(Taille,SizeOf(Taille));
            Fichier.Read(Buffer,Taille);
            NouvelleCitation^.Opus := StrNew(Buffer);
            Fichier.Read(NouvelleCitation^.Page,SizeOf(NouvelleCitation^.Page));
            Fichier.Read(Taille,SizeOf(Taille));
            Fichier.Read(Buffer,Taille);
            NouvelleCitation^.Clefs := StrNew(Buffer);
            (* Ajout du nouvel élément à la liste chaînée *)
            AjoutElementListeChainee(NouvelleCitation,TeteListe,QueueListe);
            Inc(Compteur);
          end;
        Fichier.Free;
      except
        WriteLn('*** Erreur de lecture du fichier ! ***');
      end;
    End;
    Le code source complet :
    varrecs.zip
    Règles du forum
    Cours et tutoriels Pascal, Delphi, Lazarus et Assembleur
    Avant de poser une question, consultez les FAQ Pascal, Delphi, Lazarus et Assembleur
    Mes tutoriels et sources Pascal

    Le problème en ce bas monde est que les imbéciles sont sûrs d'eux et fiers comme des coqs de basse cour, alors que les gens intelligents sont emplis de doute. [Bertrand Russell]
    La tolérance atteindra un tel niveau que les personnes intelligentes seront interdites de toute réflexion afin de ne pas offenser les imbéciles. [Fiodor Mikhaïlovitch Dostoïevski]

Discussions similaires

  1. Opérations sur plusieurs fichiers
    Par arnest dans le forum Macros et VBA Excel
    Réponses: 1
    Dernier message: 10/03/2008, 11h27
  2. Opération sur (gros) fichier
    Par sloshy dans le forum C
    Réponses: 8
    Dernier message: 24/10/2007, 19h24
  3. Opération sur un fichier de log
    Par bebert49 dans le forum Shell et commandes GNU
    Réponses: 7
    Dernier message: 26/04/2007, 11h04
  4. Opération sur un fichier XML
    Par espadon1 dans le forum Modules
    Réponses: 1
    Dernier message: 10/06/2006, 10h25
  5. [débutant] Opération sur un fichier XML
    Par espadon1 dans le forum Modules
    Réponses: 5
    Dernier message: 31/05/2006, 11h38

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