menu
  Home  ==>  articles  ==>  colibri_helpers  ==>  u_c_direct_access_variable_file   

u_c_direct_access_variable_file - John COLIBRI.


1 - Introduction

1.1 Historique

Les disquettes de l'Apple ][ pouvaient contenir 112.000 octets. Je les ai utilisées pour gérer toutes mes commandes pendant des années. Un des problème les plus immédiat fut de pouvoir stocker efficacement des adresses. En effet, certaines personnes ont une adresse simple:
Mr Jean DUPOND
5 Av de la Paix
75005 PARIS
alors que pour d'autres clients c'était un peu plus long:
Mr Jean Pierre COURTOIS DUGENOU
Résidence Les Peupliers
Val MireBois
Bâtiment 8 Escalier 5
16367 LES CONDEES SUR SENLIS
Un fichier de taille fixe souffre des mêmes inconvénient qu'un ARRAY:
  • soit la taille est calculée trop juste, et certaines adresses ne pourront être stockées
  • soit l'allocation est trop généreuse et une gâchis est fatal.
Une première solution est de stocker les adresses dans des fichiers ASCII munis d'un quelconque système de balises <début d'adresse> et <fin d'adresse>. C'est la solution que nous avions adoptées pour notre bibliographie (chaque livre pouvant avoir plusieurs auteurs, des mots clés en nombre variable, et un descriptif aussi variable.

Pour la gestion ceci n'était pas assez efficace: le fichier ASCII avec balise doit être parcouru séquentiellement. Tant que je pouvais compter mes clients sur deux mains, pas de problèmes, mais au-delà d'une centaine le temps de recherche devient prohibitif.

D'où la seconde solution consistant à répartir l'information en deux fichiers:

  • un premier fichier contient la suite des caractère ASCII de chaque adresse.
  • un second fichier ayant des fiches de taille fixe contient les positions des adresses dans le premier fichier.
Nous bénéficions ainsi d'un stockage compace, tout en gardant l'accès direct.

La technique de stockage de la position des adresse peut varier:

  • soit la position et la taille
  • soit la position de début et la position de fin
  • soit uniquement la position, le fichier variable contenant:
    • soit la taille
    • soit un marqueur de fin de chaîne (#0 par exemple)
Ces trois solutions sont optimales au niveau place. Les disquettes de l'Apple étant ce qu'elles étaient, il vallait mieux se prémunir contre un secteur foireux, et le stockage dans le fichier variable de la taille de chaque chaîne (ou un marqueur final) permettait de relire le fichier variable sans l'aide du fichier d'accès. Pour faciliter une éventuelle reconstruction, j'avais aussi ajouté à chaque adresse, le numéro de fiche dans le fichier d'accès: au pire je perdais 512 ou 1024 octets d'adresses, mais le reste des données était sauf.

La version présentée ici n'est qu'une version dépoussiérée destinée essentiellement à stocker les données des logs HTTP bruts. La particularité de ces logs est que plusieurs zones peuvent être de taille variable (les URLs, les noms de pages, les noms de machines. J'ai donc ajouté la possibilité de placer dans chaque "champ" un identificateur de champ.

1.2 Le format retenu

Le fichier d'accès contient dans chaque fiche:
  • la position de la partie variable dans le fichier variable
  • les coordonnées correspondant au fichier utilisateur: numéro de fiche et numéro de champ (dans le cas des logs, (ligne 14, champ URL) puis (ligne 14, champ page_à_telecharger), par exemple
  • la taille de la partie variable
Le fichier variable contient pour chaque champ variable:
  • les coordonnées correspondant au fichier utilisateur: numéro de fiche et numéro de champ (dans le cas des logs, (ligne 14, champ URL) puis (ligne 14, champ page_à_telecharger), par exemple
  • la taille de la partie variable
  • les octets variables

2 - Utilisation

2.1 Le ficher variable

L'interface est la suivante:

    type t_variable_field_headerrecord
                                    m_recordm_fieldm_lengthInteger;
                                  end;

         c_variable_fileclass(c_basic_file)
                            public
                              m_first_free_positionInteger;
                              m_variable_field_headert_variable_field_header;

                              Constructor create_variable_file(p_namep_file_nameString); Virtual;

                              function f_force_createBooleanOverride;
                              procedure append_string(var pv_variable_field_headert_variable_field_header;
                                  p_stringStringvar pv_string_positionInteger);
                              procedure read_string(p_string_positionInteger;
                                  var pv_variable_field_headert_variable_field_header;
                                  var pv_stringString);

                              Destructor DestroyOverride;
                          end;

Pour les données:

  • t_variable_field_header définit l'en-tête figurant avant la partie variable. Elle comporte:
    • m_record: le numéro de fiche dans l'application utilisatrice (la ligne du log HTTP, par exemple)
    • m_field: le numéro du champ dans l'application utilisatrice (1 pour l'URL, 2 pour le service etc)
    • m_length: la taille de la partie variable qui suit
      Integer;
  • dans la classe c_variable_file
    • m_first_free_position: la position du premier "trou" dans le fichier. La gestion d'une "free-list" n'est pas implémentée dans cette version, et ce champ est inutilisé (mais les 4 octets sont réservés au début du fichier disque).
    • m_variable_field_header: la "fiche courante en mémoire" pour ce fichier
Et pour les méthodes:
  • create_variable_file: initialize les champs de la classe
  • f_force_create: crée un nouveau fichier disque en détruisant le précédent au besoin
  • append_string: ajoute une chaîne à la fin du fichier. La procédure remplit le champ m_length et retourne aussi la position du premier octet stocké
  • read_string: relit une chaîne dont on fournit la position de départ. Remplit aussi l'en-tête

2.2 Le ficher d'accès

L'interface est la suivante:

    type t_direct_access_recordrecord
                                   m_offsetInteger;
                                   m_variable_field_headert_variable_field_header;
                                 end;

         c_direct_access_variable_fileclass(c_basic_file)
                                          public
                                            m_c_variable_filec_variable_file;
                                            m_direct_access_recordt_direct_access_record;

                                            Constructor create_direct_access_variable_file(p_namep_file_nameString); Virtual;

                                            function f_force_createBooleanOverride;
                                            function f_openBooleanOverride;
                                            procedure close_fileOverride;

                                            function f_append_string(p_recordp_fieldIntegerp_stringString): Integer;
                                            function f_read_stringString;

                                            Destructor DestroyOverride;
                                          end;

Pour les données:

  • t_direct_access_record: définit le type de l'enregistrement. Il comporte:
    • m_offset: la position des données dans le fichier variable
    • m_variable_field_header: une copie de l'en-tête dans le fichier variable (redondant)
  • pour la classe c_direct_access_variable_file
    • m_c_variable_file: la classe gérant les données variables
    • m_direct_access_record: la fiche courante en mémoire
Et pour les méthodes:
  • create_direct_access_variable_file: construit la classe. Notons que p_file_name est la "racine" du nom: les extensions ".dir" et ".var" seront ajoutées pour la partie accès direct et la partie variable
  • f_force_create: crée deux fichiers vides, en détruisant toute version précédente
  • f_open: ouvre les deux fichiers
  • close_file: ferme les deux fichiers
  • f_append_string: ajoute une chaîne:
    • le programme utilisateur fournit
      • p_record: le numéro de fiche (par exemple ligne 14 du log)
      • p_field: le numéro du champ (par exemple 2 pour le Service)
      • p_string: la chaîne (par exemple "SVC3")
    • la fonction retourne le numéro de fiche dans le fichier d'accès
  • f_read_string: retourne la chaîne correspondant à la fiche courante dans le fichier d'accès. Pour changer la chaîne lue, il faut d'abord effectuer un positionnement par seek_file (position en octets)

2.3 - Répertoires et Directives de Compilation

L'unité est prévue pour être placée dans:

C:
  programs
    colibri_helpers
      classes

Vous pouvez naturellement changer cette organisation par Projet | Options | Directories

Les directives de compilation sont:

  • R+ (vérification des intervalles)
  • S+ (vérification de la pile)
  • pas d'optimisation

3 - Programmation

Rien de particulier. Les deux classes s'appuient essentiellement sur la classe u_c_basic_file.


4 - Améliorations

La version actuelle n'est de loin pas optimale. J'ai expliqué plus haut que je préférais assurer la reconstitution des fichiers en cas de problème disque. Peut-être suis-je allé un peu trop loin, et la sauvegarde avec chaque partie variable de la position dans le fichier variable ET l'identificateur de l'enregistrement est un peu trop prudent.

De façon similaire, l'utilisation du type Integer pour chaque valeur numérique est sans doûte exagérée: 4 Giga pour le nombre de champs, ou même pour la taille de la partie variable est à l'évidence surdimensionné.

Actuellement ces unités ont été essentiellent conçues pour le traitement des Logs:

  • manquent la gestion des modifications (remplacement en fin si la chaîne est plus grande, gestion des trous)
  • traitement des données autres que les String. La partie variable ne dépend pas du fait qu'il s'agit de caractères de String, mais les méthodes ne sont pas écrites.
Comme nous l'avons déjà signalé, les deux classes s'appuient essentiellement sur la classe u_c_basic_file. Or celle ci est marquée essentiellement pour sa vocation de traitement de fichier chargé dans un tampon mémoire (le programme ED pour ne pas le nommer). La partie BlockRead et BlockWrite manque un peu de cohérence, et devrait vraissemblablement être réécrite. En passant en plus par une classe intermédiaire de gestion de FILE OF (qui évite l'utilisation des SIZEOF pour gérer le fichier par fiche et non pas par octets). Nous avons maintenu l'héritage de c_basic_file:
  • pour bénéficier de la gestion des erreurs
  • pour pouvoir utiliser les possiblités de copie, archivage, changement de noms etc.
En l'absence de besoin de gestion d'erreur ou copie, une réécriture des deux fichiers à partir de FILE ne serait pas un travail très important.

Actuellement ce format est remplacé par le format plus simple décrit dans u_c_string_file.


5 - Télécharger le source

Pour télécharger, cliquez: Avec les mentions d'usage:
  • j'apprécie tous les commentaires, remarques ou critiques
  • signalez-moi les bugs que vous trouverez.

L'auteur

John COLIBRI est passionné par le développement Delphi et les applications de Bases de Données. Il a écrit de nombreux livres et articles, et partage son temps entre le développement de projets (nouveaux projets, maintenance, audit, migration BDE, migration Xe_n, refactoring) pour ses clients, le conseil (composants, architecture, test) et la formation. Son site contient des articles avec code source, ainsi que le programme et le calendrier des stages de formation Delphi, base de données, programmation objet, Services Web, Tcp/Ip et UML qu'il anime personellement tous les mois, à Paris, en province ou sur site client.

Created: jan-04. Last updated: mar-2020 - 250 articles, 620 .ZIP sources, 3303 figures
Contact : John COLIBRI - Tel: 01.42.83.69.36 / 06.87.88.23.91 - email:jcolibri@jcolibri.com
Copyright © J.Colibri   http://www.jcolibri.com - 2001 - 2020
Retour:  Home  Articles  Formations  Développement Delphi  Livres  Pascalissime  Liens  Download
l'Institut Pascal

John COLIBRI

+ Home
  + articles_avec_sources
    + bases_de_donnees
    + web_internet_sockets
    + services_web_
    + prog_objet_composants
    + office_com_automation
    + colibri_utilities
    + uml_design_patterns
    + graphique
    + delphi
    + outils
    + firemonkey
    + vcl_rtl
    + colibri_helpers
      – u_types_constants
      – u_strings
      – u_loaded
      – u_c_basic_object
      – u_c_display
      – u_dir
      – u_file
      – u_display_hex
      – u_c_file_name
      – u_c_basic_file
      – u_c_log
      – u_c_line
      – handle_files
      – u_c_path_segments
      – u_c_text_file
      – u_c_direct_acccess
      – u_c_string_file
      – u_c_file_of
    + colibri_skelettons
    + admin
  + formations
  + developpement_delphi
  + présentations
  + pascalissime
  + livres
  + entre_nous
  – télécharger

contacts
plan_du_site
– chercher :

RSS feed  
Blog