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 :

Équivalent de Seek pour un TextFile


Sujet :

Langage Delphi

  1. #1
    Membre confirmé Avatar de WebPac
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    947
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2004
    Messages : 947
    Points : 512
    Points
    512
    Par défaut Équivalent de Seek pour un TextFile
    Bonjour tous, j'utilise des textfiles, je dois remonter le curseur dans le fichier d'une ligne, après quelques petites recherches, j'utilise seek et FilePos tout content d'avoir trouvé rapidement.
    Et la, le compilateur dit 'Types Incompatibles', je fais donc une recherche plus poussée et voici ce que je trouve dans l'aide :
    Seek Place la position en cours d'un fichier typé ou non sur le composant spécifié. Ne s'utilise pas avec les fichiers texte.
    Je lis tout le reste et aucun équivalent pour les fichiers texte.

    Connaissez-vous une autre méthode qui ne soit pas de fermer le fichier pour le rouvrir et relire ?

    Merci d'avance.

  2. #2
    Rédacteur


    Profil pro
    Inscrit en
    Janvier 2003
    Messages
    7 171
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2003
    Messages : 7 171
    Points : 15 060
    Points
    15 060
    Billets dans le blog
    1
    Par défaut
    Pourquoi ne pas utiliser un TStringList, cf LoadFromFile ?

  3. #3
    Inactif  
    Avatar de Mac LAK
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    3 893
    Détails du profil
    Informations personnelles :
    Âge : 49
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Octobre 2004
    Messages : 3 893
    Points : 4 846
    Points
    4 846
    Par défaut
    Je ne connais pas d'autre méthode que celles-ci :
    - Charger intégralement le fichier en RAM, dans un TStringList (consomme beaucoup de RAM si le fichier est très grand).
    - Revenir au début du fichier, lire le nombre de lignes nécessaire "pour rien" afin de positionner le pointeur de fichier au bon endroit pour la prochaine lecture (très mauvais en performances, surtout sur les grands fichiers).
    - Ouvrir le fichier en mode binaire, faire un Seek, lire la chaîne/ligne "à la main", c'est à dire caractère par caractère, en s'arrêtant à la première paire CR/LF (#13#10). Bref, te retaper les fonctions de lecture de chaînes de caractères de A à Z en partant d'un fichier binaire (c'est lourd, crois-moi).

    Sinon, une quatrième méthode ;-) :
    - Te demander sérieusement pourquoi tu as besoin d'une telle fonction, alors que c'est en général totalement inutile... Tu as peut-être un problème d'algorithme dans ton programme.
    Mac LAK.
    ___________________________________________________
    Ne prenez pas la vie trop au sérieux, de toutes façons, vous n'en sortirez pas vivant.

    Sources et composants Delphi sur mon site, L'antre du Lak.
    Pas de question technique par MP : posez-la dans un nouveau sujet, sur le forum adéquat.

    Rejoignez-nous sur : Serveur de fichiers [NAS] Le Tableau de bord projets Le groupe de travail ICMO

  4. #4
    Inactif  

    Inscrit en
    Juillet 2004
    Messages
    46
    Détails du profil
    Informations forums :
    Inscription : Juillet 2004
    Messages : 46
    Points : 135
    Points
    135
    Par défaut Seek
    La bonne solution est de charger le fichier en RAM dans un StringList au niveau de l'occupation memoire cela n'utilse que la place necessaire pour stocker les characteres car Delphi gére chaque string dans un pointeur dont il fixe la taille à la longueur exacte

    Ce que dit Mac LAK etait vrai quand les string étaient gerer comme des shortstring actuel dont l taille faisaiot obligatoirement 255 octets donc chaque ligne de ta liste faisait 255 de long même si tu n'avais qu'un charactere.
    Mais cve temps la est revolu un string de 64 occupe 64 octets.

    Donc n bon load fromFile et apres tu utilise l'index de la liste (Malist.itemindex)

    John

  5. #5
    Inactif  
    Avatar de Mac LAK
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    3 893
    Détails du profil
    Informations personnelles :
    Âge : 49
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Octobre 2004
    Messages : 3 893
    Points : 4 846
    Points
    4 846
    Par défaut Re: Seek
    Citation Envoyé par John Fullspeed
    La bonne solution est de charger le fichier en RAM dans un StringList au niveau de l'occupation memoire cela n'utilse que la place necessaire pour stocker les characteres car Delphi gére chaque string dans un pointeur dont il fixe la taille à la longueur exacte
    Certes, John, mais tu fais comment quand ton fichier fait une dizaine de mégas ? Ca bouffe au minimum la taille du fichier sur le dur !! ;-)
    Perso, j'ai déjà eu à traiter des fichiers texte de 37 Mo... Ce n'est pas une erreur de frappe, trente-sept mégas....
    Déjà, la taille d'une allocation est arrondie aux 16 octets supérieurs (au minimum), sans compter les compteurs de référence et la structure de gestion de la chaîne. Une chaîne de 200 caractères occupe plus que 200 octets en RAM. A ça, il faut rajouter la mémoire occupée par le TStrings lui-même, bien que ça ne fasse pas le gros de l'occupation mémoire, c'est vrai.
    De plus, essaie de charger dans un TStringList un fichier de 10.000 lignes, tu verras de quoi je veux parler... A la limite, un THashedStringList, mais les performances d'un TStringList ne sont pas terribles avec beaucoup d'éléments : tu peux le vérifier en affichant le fichier ligne par ligne, du début à la fin. A partir du 1000ème élément, tu devrais commencer à voir le ralentissement à l'oeil nu. :-(
    Donc, ça consomme beaucoup de RAM si le fichier est très grand... :-D Et tout le monde n'a pas forcément un giga de RAM et un proc à 3 Ghz ! ;-)

    Citation Envoyé par John Fullspeed
    Ce que dit Mac LAK etait vrai quand les string étaient gerer comme des shortstring actuel dont l taille faisaiot obligatoirement 255 octets donc chaque ligne de ta liste faisait 255 de long même si tu n'avais qu'un charactere.
    Mais cve temps la est revolu un string de 64 occupe 64 octets.
    Inexact : une chaîne ShortString n'occupe pas forcément 256 octets (t'as oublié l'octet de longueur), c'est juste que c'est sa capacité maximale, ce qui est différent. Tu pouvais déjà, en Pascal DOS, limiter la longueur des chaînes si tu le voulais.
    Et une chaîne de 64 octets occupe plus de RAM que ça, comme je te l'ai dit (déjà, au minimum le zéro terminal pour un PChar et la longueur pour un String, plus les structures de gestion de Delphi).
    N'oublie pas : le type String de Delphi n'est qu'une encapsulation d'un PChar, avec ses avantages et inconvénients... Et un String occupe plus de place qu'un PChar, même si ce n'est que d'une vingtaine d'octets.
    Mac LAK.
    ___________________________________________________
    Ne prenez pas la vie trop au sérieux, de toutes façons, vous n'en sortirez pas vivant.

    Sources et composants Delphi sur mon site, L'antre du Lak.
    Pas de question technique par MP : posez-la dans un nouveau sujet, sur le forum adéquat.

    Rejoignez-nous sur : Serveur de fichiers [NAS] Le Tableau de bord projets Le groupe de travail ICMO

  6. #6
    Inactif  

    Inscrit en
    Juillet 2004
    Messages
    46
    Détails du profil
    Informations forums :
    Inscription : Juillet 2004
    Messages : 46
    Points : 135
    Points
    135
    Par défaut String
    Un shortstring cela fait 256 octets non modifiables
    Par contre si tu utilise string[31] cela occupe 32 octets et pas un de plus (sauf eventuellement si tu as un alignement bizarre)
    Et si tu mets packed tu forces

    La preuve
    comment tu fais un enregistrement?

    Type enreg= record

    Nom:String[25]
    Prenom:String[15]
    end

    et si tu prends size of Enreg....

    Pour être clair

    un string c'est une adresse sur une zone faisant X caracteres(byte) de longueur

    un PChar c'est une adresse sur une zone de X+1 caracteres le supplementaire contennant le zero terminal

    un Shortstring c'est array[0...255] of char

    et string[x] c'est array[0..x] of char


    C'est du moins comme cela que c'est explique dans Delphi
    Tu as raison quand tu parles de l'objet lui meme il occupe de la place mais c'est proportionnellement negligeable.

    ton fichier texte de 34 Mo je reve d 'avoir un fichier comme cela pour voir justement tous les problemes que cela pose mais j'ai toujours eu que des petits (quelques megas)

    Le chaergement d'un gros fichier j'ai essaye une fois cela prends de fait beaucoup de temps mais j'avais trouve une combine

    John

  7. #7
    Inactif  
    Avatar de Mac LAK
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    3 893
    Détails du profil
    Informations personnelles :
    Âge : 49
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Octobre 2004
    Messages : 3 893
    Points : 4 846
    Points
    4 846
    Par défaut Re: String
    Citation Envoyé par John Fullspeed
    Un shortstring cela fait 256 octets non modifiables
    J'avoue que je n'utilise pas ShortString : je sais juste que c'est le "nouveau nom" des String du Pascal DOS.

    Citation Envoyé par John Fullspeed
    Par contre si tu utilise string[31] cela occupe 32 octets et pas un de plus (sauf eventuellement si tu as un alignement bizarre)
    Oui, c'est ce que je te disais pour Pascal DOS, avec l'octet de longueur évidemment à chaque fois.

    Citation Envoyé par John Fullspeed
    un string c'est une adresse sur une zone faisant X caracteres(byte) de longueur
    C'est un peu plus complexe que ça, en interne, mais vu de l'extérieur, oui.
    Il faut aussi stocker cette longueur et les compteurs de référence pour la libération automatique des chaînes.

    Citation Envoyé par John Fullspeed
    un PChar c'est une adresse sur une zone de X+1 caracteres le supplementaire contennant le zero terminal
    En fait, un String et un PChar, c'est à peu près la même chose en Delphi. Simplement, le PChar n'est pas protégé, le String l'est.
    Exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    Const
         CstStr = 'Chaîne avec un zéro dedans'+#0+'et tu verras pas cette partie.' ;
    begin
         Edit1.Text:='('+IntToStr(Length(CstStr))+') "'+CstStr+'"';
    end;
    Tu vas voir ceci dans ton TEdit :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    (57) "Chaîne avec un zéro dedans
    La chaîne est coupée au niveau du caractère nul, et tu n'en vois pas la suite. Par contre, sa longueur est correcte.

    Citation Envoyé par John Fullspeed
    un Shortstring c'est array[0...255] of char
    et string[x] c'est array[0..x] of char
    Là, par contre, oui. Mais un String[N] n'est pas un String "sans crochets", qui est plus un PChar qu'un array of char.

    Citation Envoyé par John Fullspeed
    C'est du moins comme cela que c'est explique dans Delphi
    C'est vrai, mais il faut se méfier des explications "de compréhension" par rapport à la réalité. Le plus bel exemple du monde est le modèle orbital de l'atome : physiquement, c'est complètement faux, voire à l'opposé de la réalité. Pourtant, ça explique fabuleusement bien les liaisons atomiques, malgré le fait que ce soit faux... ;-)

    Citation Envoyé par John Fullspeed
    Tu as raison quand tu parles de l'objet lui meme il occupe de la place mais c'est proportionnellement negligeable.
    Tout dépend de la taille de ta chaîne, voyons... C'est négligeable sur une chaîne de 25.000 caractères, mais ça ne l'est pas pour une chaîne vide (saut de ligne) !!
    La structure de gestion doit faire entre 4 et 32 octets, j'avoue que je n'ai jamais fouillé précisemment pour le savoir.

    Citation Envoyé par John Fullspeed
    ton fichier texte de 34 Mo je reve d 'avoir un fichier comme cela pour voir justement tous les problemes que cela pose mais j'ai toujours eu que des petits (quelques megas)
    37 Mo, pas 34... :-D
    C'est la liste des jeux en sortie XML générée par l'émulateur MAME qui fait ce poids ( http://www.mame.net ). Seules les ROMS sont illégales à télécharger, l'émulateur est freeware et il n'a pas besoin des roms pour sortir ce fichier.

    Citation Envoyé par John Fullspeed
    Le chaergement d'un gros fichier j'ai essaye une fois cela prends de fait beaucoup de temps mais j'avais trouve une combine
    Moi aussi : je le lisais en binaire, par gros blocs, et je "refabriquais" les lignes à la main. C'est pour ça que je disais que c'était lourd à faire : j'ai déjà pratiqué... :-D
    Mac LAK.
    ___________________________________________________
    Ne prenez pas la vie trop au sérieux, de toutes façons, vous n'en sortirez pas vivant.

    Sources et composants Delphi sur mon site, L'antre du Lak.
    Pas de question technique par MP : posez-la dans un nouveau sujet, sur le forum adéquat.

    Rejoignez-nous sur : Serveur de fichiers [NAS] Le Tableau de bord projets Le groupe de travail ICMO

  8. #8
    Membre confirmé Avatar de WebPac
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    947
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2004
    Messages : 947
    Points : 512
    Points
    512
    Par défaut
    Merci pour toutes ces réponses, je ne sais pas si vous m'avez pas oublié.

    Finalement, j'ai retenu la solution de Mac LAK qui est de revoir mon algorithme, enfin, je l'ai pétassé pour que ça passe, c'est du rafistolage, mais quand on doit avancer....

    Sinon une fois j'ai aidé un gars en C++ (je suis modo C++ sur un autre site) qui avait un bug pour placer son curseurs dans un énorme fichier, qui dépassait, tenez vous bien : 2 Go. Et non, je n'ai pas non plus dérappé sur le clavier, deux Giga octets.

    Et le problème venait que le fseek en C++ (mon langage d'origine) prend un long int en entrée et 2 Go ça fait exactement 2^31 soit un long int signé (en enlevant le bit du signe on aurrait pû gagner). Mais on a résolu le problème avec une autre fonction qui n'est pas limitée au long int.

    Bon j'arrête de raconter ma vie et retourne au boulot.

    PS : C'est ps glop qu'ils n'aient pas pensé faire un seek pour les TextFile

    PPS : c'est bizarre, je n'ai pas reçu de notification par mail pour les réponses de ce sujet.

  9. #9
    Inactif  
    Avatar de Mac LAK
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    3 893
    Détails du profil
    Informations personnelles :
    Âge : 49
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Octobre 2004
    Messages : 3 893
    Points : 4 846
    Points
    4 846
    Par défaut
    Citation Envoyé par WebPac
    Merci pour toutes ces réponses, je ne sais pas si vous m'avez pas oublié.
    Meuh non, t'inquiètes pas !!! ;-)

    Citation Envoyé par WebPac
    Finalement, j'ai retenu la solution de Mac LAK qui est de revoir mon algorithme, enfin, je l'ai pétassé pour que ça passe, c'est du rafistolage, mais quand on doit avancer....
    Ca, les seek sur du texte...

    Citation Envoyé par WebPac
    Sinon une fois j'ai aidé un gars en C++ (je suis modo C++ sur un autre site) qui avait un bug pour placer son curseurs dans un énorme fichier, qui dépassait, tenez vous bien : 2 Go. Et non, je n'ai pas non plus dérappé sur le clavier, deux Giga octets
    Il essayait d'éditer à la main son swap Windows, ou quoi ???? Ou une base Oracle ?? Au fou !!!!!! :-D

    Citation Envoyé par WebPac
    Et le problème venait que le fseek en C++ (mon langage d'origine) prend un long int en entrée et 2 Go ça fait exactement 2^31 soit un long int signé (en enlevant le bit du signe on aurrait pû gagner). Mais on a résolu le problème avec une autre fonction qui n'est pas limitée au long int.
    Bah, si ça peut te rassurer, c'est pareil sous Delphi. Faut passer par l'API Windows pour obtenir, par exemple, la taille d'un fichier de plus de 2 Go.

    Citation Envoyé par WebPac
    PS : C'est ps glop qu'ils n'aient pas pensé faire un seek pour les TextFile
    En fait, c'est pas possible "comme ça", tout simplement, ou alors le paramètre du Seek devrait être un numéro de ligne... Ce qui veut dire soit parcourir le fichier séquentiellement et compter, soit maintenir une table des index (éventuellement construite dynamiquement) de chaque début de ligne.

    Citation Envoyé par WebPac
    PPS : c'est bizarre, je n'ai pas reçu de notification par mail pour les réponses de ce sujet.
    Parfois, elle arrivent "en bloc", et si tu suis le forum en temps réel (ou que tu restes connecté en permanence), elle n'arrivent parfois pas du tout.
    Mac LAK.
    ___________________________________________________
    Ne prenez pas la vie trop au sérieux, de toutes façons, vous n'en sortirez pas vivant.

    Sources et composants Delphi sur mon site, L'antre du Lak.
    Pas de question technique par MP : posez-la dans un nouveau sujet, sur le forum adéquat.

    Rejoignez-nous sur : Serveur de fichiers [NAS] Le Tableau de bord projets Le groupe de travail ICMO

  10. #10
    Rédacteur
    Avatar de Pedro
    Profil pro
    Inscrit en
    Octobre 2003
    Messages
    5 411
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2003
    Messages : 5 411
    Points : 8 078
    Points
    8 078
    Par défaut
    Salut

    Je propose de dériver un TFileStream vers un TTextFileStream afin d'utiliser les streams (pratique) et de surcharger les opérations de lecture/ecriture pour les fichiers textes...
    Je pense que c'est très faisable...
    Pedro
    Aucune réponse aux sollicitations techniques par MP

    Faut pas attendre d'en avoir besoin pour s'en servir... (Lucien Stéphane)

    Les pages Source C'est bon. Mangez-en!
    Le défi Delphi
    Règles du forum - FAQ Delphi - Pensez au chtit
    Aéroclub Bastia Saint-Exupéry

  11. #11
    Membre confirmé Avatar de WebPac
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    947
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2004
    Messages : 947
    Points : 512
    Points
    512
    Par défaut
    Si des spécialistes confirment ce que tu dis, je fouillerais plus ta solution, mais n'ayant pas une grosse expérience des streams et ayant trouvé une alternative (pour le moment, j'aimerais bien trouver une vrai solution), je n'essaierai pas actuellement.

    Merci toujours pour cette idée.

  12. #12
    Membre averti
    Profil pro
    Inscrit en
    Septembre 2003
    Messages
    298
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2003
    Messages : 298
    Points : 318
    Points
    318
    Par défaut
    Tu peux regarder du coté des Memory Mapped Files (API Windows) pour accéder au 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
    var file_, map : dword; 
        buf: pointer; 
    begin 
      file_ := CreateFile('c:\file1.txt', GENERIC_READ, FILE_SHARE_READ, nil, OPEN_EXISTING, 0, 0); 
      if file_ <> INVALID_HANDLE_VALUE then 
        try 
          map := CreateFileMapping(file_, nil, PAGE_READWRITE, 0, 0, nil); 
          if map <> 0 then 
            try 
              buf := MapViewOfFile(map, FILE_MAP_ALL_ACCESS, 0, 0, 0); 
              if buf <> nil then 
                try 
     
                  // now here you have your file1.txt in memory 
                  // beginning at pointer "buf" 
     
                finally UnmapViewOfFile(buf) end; 
            finally CloseHandle(map) end; 
        finally CloseHandle(file_) end; 
    end; 
     
    {
    This logic maps your complete file into memory. It's not COPIED into
    memory, only MAPPED. In the moment where you access the single bytes
    of the file in memory, Windows internally reads the file for you in the
    fastest possible way. }

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

Discussions similaires

  1. équivalent de DragQueryFile pour une URL ?
    Par OutOfRange dans le forum Delphi
    Réponses: 2
    Dernier message: 14/10/2006, 11h24
  2. Réponses: 3
    Dernier message: 18/12/2005, 18h49
  3. Quel est l'équivalent de Findcomponent pour les Forms ?
    Par Ben_Le_Cool dans le forum Composants VCL
    Réponses: 12
    Dernier message: 23/09/2005, 12h48
  4. équivalent SQL*Loader pour FB / IB
    Par djeant dans le forum Outils
    Réponses: 9
    Dernier message: 10/01/2005, 21h26
  5. Réponses: 3
    Dernier message: 09/04/2004, 23h35

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