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 Delphi Discussion :

Un fichier ne peut pas contenir de string sans préciser sa taille


Sujet :

Langage Delphi

  1. #1
    Futur Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Mars 2012
    Messages
    12
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Algérie

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Tourisme - Loisirs

    Informations forums :
    Inscription : Mars 2012
    Messages : 12
    Points : 8
    Points
    8
    Par défaut Un fichier ne peut pas contenir de string sans préciser sa taille
    (Delphi/Pascal)
    Bonjour,

    Toujours j'ai des problèmes avec DELPHI et les strings, le problème cette fois est : un fichier (pas un fichier texte) ne peut pas contenir une string sans préciser sa taille.

    Par exemple : cette déclaration est interdite :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    type etudiant=record
           Matr: integer;
           Nom,Pren: string; {string de taille non précisée}
           .
           .
           .
    end;
     
    var F: File of etudiant;
    Et je demande une solution idéale pour ce problème (en sachant que je ne peux pas préciser la taille).

  2. #2
    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 458
    Points
    15 458
    Billets dans le blog
    9
    Par défaut
    Bonjour !

    Il faut bien que la taille de l'enregistrement soit définie pour que le compilateur puisse gérer le fichier.

    D'ailleurs, quel est l'intérêt d'une chaîne de longueur indéfinie pour contenir un nom et un prénom ?

    Si tu veux, tu peux remplacer string par shortstring, mais cela revient toujours à définir la taille maximale de la chaîne.

    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
    program fileOfRec;
     
    {$APPTYPE CONSOLE}
     
    type
      tEtudiant = record
                    mat: integer;
                    //nom: string[99];
                    nom: shortString;
                  end;
     
    var
      f: file of tEtudiant;
     
    begin
      { TODO -oUser -cConsole Main : placez le code ici }
    end.
    Mon site personnel consacré à MSEide+MSEgui : msegui.net

  3. #3
    Expert éminent sénior
    Avatar de Paul TOTH
    Homme Profil pro
    Freelance
    Inscrit en
    Novembre 2002
    Messages
    8 964
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Freelance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2002
    Messages : 8 964
    Points : 28 445
    Points
    28 445
    Par défaut
    un "file of" utilise une structure de taille fixe, donc soit tu fixes la taille de tes chaînes, soit tu n'utilises pas un "file of"
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

  4. #4
    Membre éprouvé
    Avatar de Dr.Who
    Inscrit en
    Septembre 2009
    Messages
    980
    Détails du profil
    Informations personnelles :
    Âge : 45

    Informations forums :
    Inscription : Septembre 2009
    Messages : 980
    Points : 1 294
    Points
    1 294
    Par défaut
    Le plus simple et rapide : CSV

    avec une simple TStringList

    il vaux mieux utiliser une convertion StrToInt / IntToStr par exemple sur un champ de type entier ou flottant que de devoir faire une procedure lourde pour l'enregistrement et l'ouverture du fichier.

    En toute sincérité, il est préférable d'eviter au possible les structures FILE OF et préférer l'utilisation de fichiers CSV, XML ou d'une base de données.

    C'est plus simple, plus pratique, et rapide à mettre en place.

    avec CSV par TStringList tu peux espérer de très bonne performances avec des fichiers inférieur a 10Mo de 10000/20000 lignes par 100 colonnes.

    CSV est l'ancêtre de la base de donnée.

    pour ce faire :

    il faut 2 TStringList, une qui contient le fichier et une pour lire chaque ligne.

    à peu de chose prés, ça donne ça (réalisé en quelques secondes) :

    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
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    type
      TMonCsv = class
      private
        fLI  : integer;
        fDB  : TStringList;
        fRow : TStringList;
        function getField(Row, Col: integer): string;
        procedure setField(Row, Col: integer; const Value: string);
      public
        property Field[Row, Col: integer] : string read getField write setField;
        function add(aColCount: integer): integer;
        procedure LoadFromFile(aFileName: string);
        procedure SaveToFile(aFileName: string);
        constructor Create; reintroduce;
        destructor Destroy; override;
      end;
     
    { TMonCsv }
     
    function TMonCsv.add(aColCount: integer): integer;
    begin
      fLI := -1;
      fRow.Clear;
      while fRow.Count < aColCount do
        fRow.Add('');
      fLI := fDB.Add(fRow.DelimitedText);
    end;
     
    constructor TMonCsv.Create;
    begin
      fDB  := TStringList.Create;
      fRow := TStringList.Create;
      fRow.Delimiter := ';';
      fRow.QuoteChar := '"';
      fRow.StrictDelimiter := true;
      fLI := -1;
    end;
     
    destructor TMonCsv.Destroy;
    begin
      fRow.Free;
      fDB.Free;
      inherited;
    end;
     
    function TMonCsv.getField(Row, Col: integer): string;
    begin
      if Row <> fLI then
      begin
        fLI := Row;
        fRow.DelimitedText := fDB[fLI];
      end;
      result := fRow[col];
    end;
     
    procedure TMonCsv.LoadFromFile(aFileName: string);
    begin
      fDB.LoadFromFile(aFileName);
    end;
     
    procedure TMonCsv.SaveToFile(aFileName: string);
    begin
      fDB.SaveToFile(aFileName);
    end;
     
    procedure TMonCsv.setField(Row, Col: integer; const Value: string);
    begin
      if Row <> fLI then
      begin
        fLI := Row;
        fRow.DelimitedText := fDB[fLI];
      end;
      fRow[col] := Value;
      fDB[fLI]  := fRow.DelimitedText;
    end;

    à utiliser somme tout logique comme un simple TListBox.

    MonCSV.LoadFromFile('BaseEleves.csvdb');
    (...)
    MonCSV.field[X, 0] := IntToStr(CalculerMoyenne());
    (...)
    MonCSV.SaveToFile('BaseEleves.csvdb');


    Avantage majeur, c'est réutilisable pour TOUT tes programmes que necessites l'utilisation de petit fichier de données.

    C'est ce que j'utilise à mon boulot pour gérer :
    Catalogues, Prix, Base produits, Emplacements entrepots, Convertions catalogues fournisseurs etc.
    Avec des données relativement grosses (fichiers > 20Mo), + de 250000 références etc.
    Pour des temps de traitement inférieur a 5 secondes sur les grosses grosses étapes.
    Par exemple, dans mon application qui permet de faire les récéptions produits, j'ai un fichier CSV qui contient les références, emplacements et stock d'environ 2 à 3 Mo. On scan un produit à l'aide d'une douchette, le programme réagis en moins de 30ms pour afficher les informations relatives a ce dernier, avec toutes les autres gestions à coté (validité de la référence, correction auto de stock selon paramètres, affichage propre etc).

    on pourrait croire que CSV c'est tout pourri, il n'en est rien, c'est aussi rapide qu'une base MySQL, pour un déploiement 1000 fois plus simple et rapide que l'installation d'un serveur etc.
    Bien sur, on sera limité en nombre d'éléments présent dans le fichiers, un TStringList commence à perdre en rapidité au dela de 5-8Mo par texte ou environ de 20000 à 100000 lignes.

    Dans une autre appli, qui centralise les catalogues fournisseurs en CSV, tirés de données CSV ou XML (donc convertion en plus), il me faut moins de quelques secondes pour charger le gros catalogue CSV (+ 250000 références) (et encore j'ai du ralentir le chargement pour que l'on puisse le voir), une fois chargé, l'accés au données des lignes CSV ou leur modification est instantané (environ 40 colonnes et 2 à 3Ko par lignes).

    Bon code !
    [ Sources et programmes de Dr.Who | FAQ Delphi | FAQ Pascal | Règlement | Contactez l'équipe ]
    Ma messagerie n'est pas la succursale du forum... merci!

  5. #5
    Membre confirmé
    Homme Profil pro
    Santé
    Inscrit en
    Septembre 2010
    Messages
    290
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Santé
    Secteur : Santé

    Informations forums :
    Inscription : Septembre 2010
    Messages : 290
    Points : 534
    Points
    534
    Par défaut
    Citation Envoyé par Dr.Mimo Voir le message
    Et je demande une solution idéale pour ce problème (en sachant que je ne peux pas préciser la taille).
    Sinon, pour des Strings et bien d'autres structures de données de taille variable, une solution plus générale existe :

    - le fichier de sauvegarde binaire.

    Pour les temps d'accès, je pense que si le fichier est bien pensé, avec une table dans le Header par exemple, ça doit le faire...

  6. #6
    Futur Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Mars 2012
    Messages
    12
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Algérie

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Tourisme - Loisirs

    Informations forums :
    Inscription : Mars 2012
    Messages : 12
    Points : 8
    Points
    8
    Par défaut Remerciement
    Merci Pour chacun qui a posé une réponse, mais ... c'est quoi TStringList?
    est-ce qu'un fichier peut contenir une liste chainée? et Merci ...

  7. #7
    Futur Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Mars 2012
    Messages
    12
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Algérie

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Tourisme - Loisirs

    Informations forums :
    Inscription : Mars 2012
    Messages : 12
    Points : 8
    Points
    8
    Par défaut Paul TOTH ...
    merci pour ta réponse ...
    peux-je utiliser la procedure Seek(); avec les fichiers non-typés ('File') ...
    pour accéder aux enregistrement que je veux traiter?


    Et merci

  8. #8
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 460
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 460
    Points : 24 874
    Points
    24 874
    Par défaut
    C'est un peu facile le CSV et la TStringList, il faut rappeler que Dr.Mimo est étudiant, le format binaire en "file of" est peut-être une thématique imposée qu'il doit développer dans son projet !
    Mais à part ça, le CSV est aussi un système de stockage simple, tu trouveras de nombreux sujet sur le forum pour traiter un CSV

    Un sujet qui devrait te plaire Enregistrement de record non finalisé, si tu souhaite concerne des chaines à longueur variable mais cela utilise la lib de SJRD, cela te masquera une partie intéressante du code qu'il se préférable que la code toi même !

    Quel composant pour présenter des enregistrements ? très intéressant pour l'utilisation du Seek !

    Si tu ne fixe pas la longueur de la chaine, cela va compliquer le seek
    tu ne pourras pas accéder au nieme élément sans avoir lu au prélable ceux que le précéde !
    C'est justement tout la complexité du type VARCHAR dans une Base de données !
    Il y a plusieurs méthodes :
    - indiquer la longueur de l'enreg à son début, cela te permettra de faire des "bonds" dans le fichier
    - maintenir un fichier d'index qui donne la position de chaque enregistrement
    - isoler les chaines dans une autre section du fichier, en stockant la position de la chaine dans la structure
    ...

    Simplifie toi la vie avec ShortString ou String[], c'est efficace, beaucoup de vieille DB comme Paradox ou DBase utilisait ce principe de chaine fixe !
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  9. #9
    Membre émérite Avatar de edam
    Homme Profil pro
    Développeur Delphi/c++/Omnis
    Inscrit en
    Décembre 2003
    Messages
    1 894
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Maroc

    Informations professionnelles :
    Activité : Développeur Delphi/c++/Omnis
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Décembre 2003
    Messages : 1 894
    Points : 2 771
    Points
    2 771
    Par défaut
    pourquoi pas simplement utilisé une base données?? accées,firebird,...
    PAS DE DESTIN, C'EST CE QUE NOUS FAISONS

  10. #10
    Membre éprouvé
    Avatar de Dr.Who
    Inscrit en
    Septembre 2009
    Messages
    980
    Détails du profil
    Informations personnelles :
    Âge : 45

    Informations forums :
    Inscription : Septembre 2009
    Messages : 980
    Points : 1 294
    Points
    1 294
    Par défaut
    Je crois que "apprendre" les file of ... même si il faut les connaitre pour savoir pourquoi on ne doit pas les utiliser ... est totalement inutile.

    Il est mieux d'apprendre à utiliser TStringList pour les CSV et les TStream/TFileStream/TMemoryStream car c'est ce qu'on utilise dans les entreprises.

    Si je vois un seul "file of" dans nos programmes, je vire le mec.
    [ Sources et programmes de Dr.Who | FAQ Delphi | FAQ Pascal | Règlement | Contactez l'équipe ]
    Ma messagerie n'est pas la succursale du forum... merci!

  11. #11
    Expert éminent sénior
    Avatar de Paul TOTH
    Homme Profil pro
    Freelance
    Inscrit en
    Novembre 2002
    Messages
    8 964
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Freelance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2002
    Messages : 8 964
    Points : 28 445
    Points
    28 445
    Par défaut
    Citation Envoyé par Dr.Who Voir le message
    Je crois que "apprendre" les file of ... même si il faut les connaitre pour savoir pourquoi on ne doit pas les utiliser ... est totalement inutile.

    Il est mieux d'apprendre à utiliser TStringList pour les CSV et les TStream/TFileStream/TMemoryStream car c'est ce qu'on utilise dans les entreprises.

    Si je vois un seul "file of" dans nos programmes, je vire le mec.
    mince, tu m'aurais viré

    la dernière fois que j'ai fait du "file of" c'était pour des élections, j'avais besoin d'une solution simple et rapide pour consulter la base des électeurs en cas de panne informatique. J'ai créer un file of avec un record de ce type:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    type
      TElecteur = record
      // électeur
        Nom        : array[0..20] of Char;
        Prenom    : array[0..20] of Char;
        Naissance: TDate;
        Electeur  : Integer;
        Bureau    : Integer;
      // Indexes
        IndexNom: Integer;
        IndexBureau: integer;
      end;
    un autre programme exportait la bdd dans un fichier sous ce format en calculant tous les indexes, le fichier était ensuite mappé en mémoire et les champs Index* permettaient de trier les électeurs
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    // nom du premier électeur trié par nom
      Electeurs[Electeurs[0].IndexNom].Nom;
    // nom du premier électeur trié par bureau
      Electeurs[Electeurs[0].IndexBureau].Nom;
    avec ça, un EXE et un .DAT sur une clé USB et hop ! n'importe quel PC permettait d'accéder aux fichier électoral.

    bon aujourd'hui j'utiliserais sans doute un SQLite ou un MySQL embarqué...mais c'était fun de le faire comme ça, d'autant qu'il n'était question que de consulter le fichier, aucune mise à jour
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

  12. #12
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 460
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 460
    Points : 24 874
    Points
    24 874
    Par défaut
    Citation Envoyé par Dr.Who Voir le message
    Il est mieux d'apprendre à utiliser TStringList pour les CSV et les TStream/TFileStream/TMemoryStream car c'est ce qu'on utilise dans les entreprises.
    Euh, tu vas vite en généralisation !
    Ce n'est pas parce que tu es un "pro" que tu utilises les bonnes méthodes, en 15 ans, j'ai vu tout et n'importe quoi et plus souvent le pire !

    la TStringList pour lire du texte, oui c'est un classique bien dégueux que beaucoup utilisent !
    Mais les TStream, je peux te dire qu'à chaque fois que je les évoquais, cela semblait être une découverte pour mes collègues, je dirais que l'utilisation même de binaire c'est déjà rarissime !

    le "file of" c'est juste un raccourci pour un BlockRead\BlockRead sur une structure, tout le monde le boude depuis D7 et les Warnings en prévention du .NET, pas parce que c'était une mauvaise technique mais surtout que c'était un système d'accès brut à la mémoire unsafe !

    Je l'ai justement utilisé la 1ere fois en 2004, un peu comme Paul, juste par curiosité et uniquement en lecture aussi !
    A peine 10 lignes de code pour passer simple file ou en TStream puisque cela remplissait une structure polymorphe

    Je suis d'accord avec Dr.Who, mieux vaut apprendre FileRead, BlockRead ou TStream.Read sur une zone mémoire, c'est plus polyvalent que "file of" que l'on hérite des langages précédent le pascal

    Citation Envoyé par Dr.Who Voir le message
    très bonne performances
    Oui avec 10Mo, avec un File of, tu peux lire un fichier de 2Go sans soucis, suffit de faire un seek pour un déplacement sur l'enregistrement souhaité !
    Avec un CV, va chercher le 100 000eme enregistrement : Fichier CSV, Compteur de lignes
    Sans parler des nombreux algos qui ne gère pas la présence d'un retour charriot comme donné d'un champ et non comme la fin d'un enregistrement !

    Citation Envoyé par Dr.Who Voir le message
    CSV est l'ancêtre de la base de donnée.
    tu vas vite en besogne !

    le file of étant une structure binaire est bien plus proche de la DB comme Paradox que le CSV
    Bien avant l'apparition de DB, des langages comme COBOL ont proposé pour
    compenser certains défaut de l'accès séquentiel, en particulier pour effectuer une recherche, les index, cela pour réduire la quantité de données lues pour rapidement retrouver un enregistrement, une technique bien connu sous le nom de ISAM
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  13. #13
    Membre émérite Avatar de edam
    Homme Profil pro
    Développeur Delphi/c++/Omnis
    Inscrit en
    Décembre 2003
    Messages
    1 894
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Maroc

    Informations professionnelles :
    Activité : Développeur Delphi/c++/Omnis
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Décembre 2003
    Messages : 1 894
    Points : 2 771
    Points
    2 771
    Par défaut
    Citation Envoyé par Dr.Who Voir le message
    Je crois que "apprendre" les file of ... même si il faut les connaitre pour savoir pourquoi on ne doit pas les utiliser ... est totalement inutile.

    Il est mieux d'apprendre à utiliser TStringList pour les CSV et les TStream/TFileStream/TMemoryStream car c'est ce qu'on utilise dans les entreprises.

    Si je vois un seul "file of" dans nos programmes, je vire le mec.
    alors sûrment tu va me vire
    , je préfère "file of byte" que les stream, j'utilise des blockread et blockwrite avec, mais bien sûr si n'est pas nécessaire d'utilisé les stream ou les tstrings, avec blockread, c'est rapide et je controlle bien mes données, surtout avec des fichiers type csv ou texte , peut être un programmeur ancien généraient du monde pascal 6
    PAS DE DESTIN, C'EST CE QUE NOUS FAISONS

Discussions similaires

  1. Réponses: 9
    Dernier message: 08/08/2016, 15h52
  2. A/S Fichier ne peut pas être ccéder
    Par ASSIA90 dans le forum Développement Windows
    Réponses: 0
    Dernier message: 08/09/2014, 23h08
  3. [AC-2007] un index ou une clé principale ne peut pas contenir une valeur null
    Par sarhouda dans le forum Access
    Réponses: 6
    Dernier message: 13/12/2012, 18h54
  4. Réponses: 3
    Dernier message: 06/03/2007, 14h15
  5. [C#][debutant] tableau String sans donner la taille ?
    Par Sylk dans le forum Windows Forms
    Réponses: 4
    Dernier message: 29/11/2005, 20h42

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