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

Delphi Discussion :

Manipulations de millions de chaines et de milliers de fichiers


Sujet :

Delphi

  1. #1
    Membre actif Avatar de lun4t1k
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    276
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Janvier 2007
    Messages : 276
    Points : 274
    Points
    274
    Par défaut Manipulations de millions de chaines et de milliers de fichiers
    Bonjour,

    Je suis devant un problème d'implémentation, ne connaissant pas toutes les facettes que me proposent delphin je m'en remet à vous.

    Je genere une série de combinaisons genre Cxxx : aa bb cc dd ee ff
    et je désire les ranger dans un fichier spécifique correspondant à la spécificité de la combinaison.

    Mon générateur s'occupe de générer toutes les combi possibles, puis selon les propriétés de la combi, je veux l'enregistrer dans le bon fichier (500 au final).

    Mon probleme: je peux bien générer une combi, voir les propriétés et la ranger dans le bon fichier. Mais je veux optimiser tout ca.
    Sachant que les deux proriétés servent a nommer le fichier.
    Propr1-Propr2.txt (il y en aura 500 avec prop1 et prop2 unique). AVec dans chaque fichier un certain nombre de combinaisons.

    Comment implémenter tout cela afin de limiter le nombre d'e/s?
    Merci a vous.
    Si ce n'est pas clair n'hésitez pas!

  2. #2
    Membre chevronné
    Avatar de Clorish
    Profil pro
    Inscrit en
    Juin 2003
    Messages
    2 474
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2003
    Messages : 2 474
    Points : 2 158
    Points
    2 158
    Par défaut
    Citation Envoyé par lun4t1k
    Comment implémenter tout cela afin de limiter le nombre d'e/s?
    Merci a vous.
    Si ce n'est pas clair n'hésitez pas!
    A voir si la memoire le permet (ce qui ne me semble pas impossible vu la taille des chaines) tu peux eventuelement stocker tes resultats en memoire avant de les copier sur le disque.
    Les TMemoryStream sont tres bien pour travailler sur des ficheirs en memoire et les charger/sauvegarder d'un bloc sur le HDD.

    Sinon opte pour des classes de gestion fichier buffurisé.

  3. #3
    Membre actif Avatar de lun4t1k
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    276
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Janvier 2007
    Messages : 276
    Points : 274
    Points
    274
    Par défaut
    Merci de ta réponse rapide.
    C'est ce que je pensais, travailler en mémoire et enregistrer par bloc.

    Le probleme principal et qu'il me faut gérer pres de 500 fichiers simultanément.
    A chaque generation, mettre combi x dans fichier de nom prop1-prop2.txt où prop1 et 2 sont les propriétes de la combinaison.

    Les TMemoryStream me semblent bien mais dans mon cas je devrais en avoir environ 500? Pour chaque fichier?

    As tu un exemple sous la main de classe de gestion de fichiers bufferisés?

  4. #4
    Modérateur

    Homme Profil pro
    Ingénieur retraité
    Inscrit en
    Octobre 2005
    Messages
    2 396
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur retraité

    Informations forums :
    Inscription : Octobre 2005
    Messages : 2 396
    Points : 3 266
    Points
    3 266
    Par défaut
    Bonjour,

    Il y a déjà eu une discussion sur un sujet similaire ici :
    http://www.developpez.net/forums/sho...ighlight=Art19
    ... et en utilisant un TFileStream tu peux même regrouper tous tes fichiers en un seul gros-fichier qui reste sur le disque et dont tu ne charges en mem-vive que la partie partie utile à l'instant "t" de longueur_N et qui commence en position_N, ... longueur_N et position_N étant mémorisés dans une structure du style "relevé topographique du gros-fichier" lors de la phase de regroupement des fichiers en un seul-gros.
    ... par contre si tes fichiers-individuels changent sans cesse de taille sans dépasser la mem-vive-dispo c'est plus souple à gérer de les conserver à l'état séparé et d'utiliser TMemoryStream.
    A+
    P.S : Le présent message n'est qu'une réponse au 1er message de cette discussion et non au message qui s'est intercalé entre-temps devant le mien.

  5. #5
    Membre actif Avatar de lun4t1k
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    276
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Janvier 2007
    Messages : 276
    Points : 274
    Points
    274
    Par défaut
    Oki merci! Le probleme n'est pas la taille du fichier en soit, c'est le nombre qui est important a gerer. il y a des millions de combis a dispatcher dans 500 (ou plus ) fichiers.

    Gerer une position_N en fonction de deux parametres, ca risque de ne pas etre evident.

    Merci je vais essayer de m orienter vers les TMemoryStream.

  6. #6
    Membre chevronné
    Avatar de Clorish
    Profil pro
    Inscrit en
    Juin 2003
    Messages
    2 474
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2003
    Messages : 2 474
    Points : 2 158
    Points
    2 158
    Par défaut
    Je ne vois pas en quoi 500 TMemoryStream serait genant.
    La classe elle meme n'ets aps plus lorde qu'un bouton et des applis a plus de 500 boutons ca se fait.

    Apres tout depends de la taille des données a ecrire. Vu que le role d'un TMemoryStream est d'ecrire des données dans la memoire vive, on risque rapidement d'etre a court de memoire.

    Dans ce cas on peut opter pour une Serie de TMEmoryStream limité a X octets.
    Apres chaques copie de chaine dans un TMemoryStream, on peut eventuelement tester la taille memoire utilisée (Property Size) et si elel depasse le quota autorisé, copier le contenu du stream dans le fichier (ouvert via un TFileStream).

    Par contre il en faut pas avoir besoin des données precedentes .. sinon ca risque d'etre plus chaud

  7. #7
    Modérateur

    Homme Profil pro
    Ingénieur retraité
    Inscrit en
    Octobre 2005
    Messages
    2 396
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur retraité

    Informations forums :
    Inscription : Octobre 2005
    Messages : 2 396
    Points : 3 266
    Points
    3 266
    Par défaut
    Re-Salut,

    Complément à mon message précédent :

    Si, une fois créés, tes fichiers sont utilisés à taille constante tu peux les regrouper en un seul comme suggéré dans le message précédent avec le TFileStream.

    Si tu tiens à conserver tes fichiers à l'état individuel non regroupés en utilisant du TMemoryStream tu peux :
    - n'utiliser qu'un seul TMemoryStream si tu n'as besoin que d'un seul fichier après l'autre,
    - ou utiliser un nombre de TMemoryStream's égal au nombre de fichiers dont tu a besoin simultanément.
    ... donc, toi seul connais tes besoins, à toi de choisir.

    Tiens, ton dernier message est apparu avant que je n'aie terminé le présent :
    c'est le nombre qui est important a gerer. il y a des millions de combis a dispatcher dans 500 (ou plus ) fichiers.
    Gerer une position_N en fonction de deux parametres, ca risque de ne pas etre evident.
    ... au début t'avais dit :
    ranger dans un fichier spécifique correspondant à la spécificité de la combinaison
    ... cela m'a fait penser qu'une fois créé, chaque groupe de combinaisons était regroupé une fois pour toutes dans un fichier nommé Propr1-Propr2.txt mais qu'une fois créé il n'y avait rien d'autre à y insérer par dispatching.

    Quand tu dis "Gerer une position_N en fonction de deux parametres ... risque de ne pas etre evident" : Rien n'empêche d'insérer dans le fichier de regroupent du type TFilestream le nom de chaque fichier "Propr1-Propr2.txt" et dont la fin du nom correspond justement à la "position_N" du début des données du fichier correspondant.
    A+

  8. #8
    Membre actif Avatar de lun4t1k
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    276
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Janvier 2007
    Messages : 276
    Points : 274
    Points
    274
    Par défaut
    Tout d'abord merci a vous pour vos réponses constructives et très indicatives.

    Je suis a la base développeur c++.
    En c++ on gere facilement les dictionnaires ou tableaux associatifs.
    N'ya t il pas un moyen de créer en delphi ou d'utiliser une telle structure?
    Ou une table de hashage?

    Explications:
    monTab['prop1-prop2.txt'].Lines.Add('le contenu a ajouter a mon stream').

    Ce n'est peut etre pas Lines.Add mais bon vous comprenez.
    Ainsi, il ne me resterait plus qu'a parcourir ce tableau pour creer et ecrire le contenu du text stream dans les fichiers.
    Si l'association monTab['prop1-prop2.txt'] existe, je rajoute a la suite.
    Il faudrait que l'acces a un element soit en temps constant.


    Le nombre de fichiers est normalement connu (on est pas l'abri de mauvais calculs maladroits )

    Qu'en pensez-vous?

    Edit: Pour eclaircir mon vocabulaire qui peut etre houleux :
    A chaque combinaison générée je regarde dans quel fichier elle va et je l'ajoute dans le bon fichier.

    Edit2:
    Quand tu dis "Gerer une position_N en fonction de deux parametres ... risque de ne pas etre evident" : Rien n'empêche d'insérer dans le fichier de regroupent du type TFilestream le nom de chaque fichier "Propr1-Propr2.txt" et dont la fin du nom correspond justement à la "position_N" du début des données du fichier correspondant.
    Precision: La taille du fichier qui regroupe toutes les positions avoisine les 800Mo (il contient les quelques millions de combis).

  9. #9
    Modérateur

    Homme Profil pro
    Ingénieur retraité
    Inscrit en
    Octobre 2005
    Messages
    2 396
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur retraité

    Informations forums :
    Inscription : Octobre 2005
    Messages : 2 396
    Points : 3 266
    Points
    3 266
    Par défaut
    Re-bonjour,

    Lun4t1k a écrit :
    Si l'association monTab['prop1-prop2.txt'] existe, je rajoute a la suite.
    ...
    A chaque combinaison générée je regarde dans quel fichier elle va et je l'ajoute dans le bon fichier.
    ... n'aurais-tu pas la possibilité de modifier ton code de façon à créer toutes les combinaisons qui réalisent l'association monTab['prop1-prop2.txt'] de façon à créer en une seule traite chaque fichier de destination avant d'attaquer le suivant ça t'éviterait d'avoir à chaque fois à regarder dans quel fichier elle va et cela faciliterait la gestion des fichiers. ?

  10. #10
    Membre actif Avatar de lun4t1k
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    276
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Janvier 2007
    Messages : 276
    Points : 274
    Points
    274
    Par défaut
    Bonne idée mais non, car la génération peut soit generer toutes les combinaisons et les enregistrer dans un seul fichier soit toutes et les ranger.

    Generer toutes les combinaisons correspondant a une assoc serait couteux a mon gout en terme de complexité et reviendrait a tester des combinaisons qui ne seront pas ecrites dans le fichier.

    Cela minimiserait l e/s mais doublerait le remplissage des fichiers.
    Le calcul des propriétés est rapide et dépend de la longueur de la combinaison (optimisé).


    PS: A mon avis...
    Merci!


    Citation Envoyé par Gilbert Geyer
    Re-bonjour,

    ... n'aurais-tu pas la possibilité de modifier ton code de façon à créer toutes les combinaisons qui réalisent l'association monTab['prop1-prop2.txt'] de façon à créer en une seule traite chaque fichier de destination avant d'attaquer le suivant ça t'éviterait d'avoir à chaque fois à regarder dans quel fichier elle va et cela faciliterait la gestion des fichiers. ?

  11. #11
    Modérateur

    Homme Profil pro
    Ingénieur retraité
    Inscrit en
    Octobre 2005
    Messages
    2 396
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur retraité

    Informations forums :
    Inscription : Octobre 2005
    Messages : 2 396
    Points : 3 266
    Points
    3 266
    Par défaut
    Ben dans ce cas utilises un array de 500 TFileStream et si l'association monTab['prop1-prop2.txt'] existe, tu l'ajoutes à la fin du FileStream correspondant ... et t'es même pas obligé dans ce cas de calculer de position_N puisqu'avec des write successifs en fin d'un TFileStream c'est l'appel au write qui ajuste la position. En plus l'array de 500 TFileStream occupe peu de place en mémoire à part quelques trucs tout le reste est sur le disque. Si tu veux te documenter sur les Stream's j'ai vu qu'il y a des infos dans la Faq ou dans les Tutoriels.
    A+

  12. #12
    Membre chevronné
    Avatar de Clorish
    Profil pro
    Inscrit en
    Juin 2003
    Messages
    2 474
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2003
    Messages : 2 474
    Points : 2 158
    Points
    2 158
    Par défaut
    Citation Envoyé par Gilbert Geyer
    En plus l'array de 500 TFileStream occupe peu de place en mémoire à part quelques trucs tout le reste est sur le disque.
    Tout a fait.
    DE plus il me semble que les TFileStream font partie des classes qui ont un acces buffurisé au fichier.
    Par contre les acces disques sont tout de meme un peu plus nombreux et couteux que des copie de TMemoryStream par blocs plus consequent.

    Apres tout est une question de choix

    J'opterais pour la solution via TFileStream a moins que le cout en acces disque soit encore trop important.

  13. #13
    Membre actif Avatar de lun4t1k
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    276
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Janvier 2007
    Messages : 276
    Points : 274
    Points
    274
    Par défaut
    D'accord je ferai un comparatif entre TMemoryStream et TFileStream pour orienter mon choix.

    L'idée du tab associatif me parait etre la plus simple et me parait assez efficace.

    Le langage en lui meme propose t il ce type d'implémentation?
    Ou en installant une librairie telle DCLx (ou qq chose comme ca)

    Sinon j'ai vu ce genre de chose relativement simple
    Tab Assoc

    Quelle est l'implementation la plus efficace selon vous? (Acces en temps constant primordial). L'acces sera la seule utilisation que j'en ferai, je pense. Il n'y aura pas de recherche, ni de tri pour l instant.


    Encore une fois merci a vous, vous m'avez fait gagné un temps précieux!
    meme si ce n'est pas que version papier!

  14. #14
    Membre chevronné
    Avatar de Clorish
    Profil pro
    Inscrit en
    Juin 2003
    Messages
    2 474
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2003
    Messages : 2 474
    Points : 2 158
    Points
    2 158
    Par défaut
    LE meilleur moyen de faire un tableaux associatif est de passer par des property indexées :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    Procedure SetTabAssoc(index : String; val : TMonRecord); 
    Function GetTabAssoc(index : String) : TMonRecord;
    Property TabAssoc[index : String] : TMonRecord Read GetTabAssoc Write SetTabAssoc;
    Je te laisse imaginer la suite ...

  15. #15
    Membre actif Avatar de lun4t1k
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    276
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Janvier 2007
    Messages : 276
    Points : 274
    Points
    274
    Par défaut
    Citation Envoyé par Clorish
    LE meilleur moyen de faire un tableaux associatif est de passer par des property indexées :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    Procedure SetTabAssoc(index : String; val : TMonRecord); 
    Function GetTabAssoc(index : String) : TMonRecord;
    Property TabAssoc[index : String] : TMonRecord Read GetTabAssoc Write SetTabAssoc;
    Je te laisse imaginer la suite...
    Je ne connais pas les Property.
    Mais j'en deduis que c'est la specification de acces:
    GetTabAssoc en lecture (le const en c++) et settabAssoc est une méthode decriture.

    Mais il manque :
    monTab : array[0..500] of TMonRecord; dans private

    Non?

    Merci a vous, je vous tiens au courant des que tout est implementé pour voir la rapidité gagnée.

  16. #16
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 586
    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 586
    Points : 25 262
    Points
    25 262
    Par défaut
    tient, pour un autre sujet, je parle de ma THashStringList, c'est le principe du Tableau Assoc justement voir ICI, je met aussi un code pour faire une liste doublement trié ... le Record pouvant bien être géré par un TObject qui peut lui même être une sous THashStringList

  17. #17
    Membre chevronné
    Avatar de Clorish
    Profil pro
    Inscrit en
    Juin 2003
    Messages
    2 474
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2003
    Messages : 2 474
    Points : 2 158
    Points
    2 158
    Par défaut
    Citation Envoyé par lun4t1k
    Je ne connais pas les Property.
    Mais j'en deduis que c'est la specification de acces:
    GetTabAssoc en lecture (le const en c++) et settabAssoc est une méthode decriture.
    C'est un outils fort pratique !!
    En fait ca rajoute une couhce d'abstraction.
    Une property est uen variable lié en ecriture/lectuer soit a une autre variable, soit a une methode getter ou setter.
    Le programme appelera la variable ou methodes associé write quand on affectera la property (partie gauche du := ) et celle associé Read quand on l'utilisera.

    DE cette maniere on peut donc facilement passer d'une simple variabel publique a une methode effectuant du code sans changer la definition publique de la classe.
    Tres partique pour mettre a jour une classe.
    Cela permet de separer la partie code de l'interface d'utilisation.

    Citation Envoyé par lun4t1k
    Mais il manque :
    monTab : array[0..500] of TMonRecord; dans private

    Non?
    Bien vu
    tu es sur la bonne voie.
    La je t'ai montré une partie speciale des property : les property tableaux ou comment acceder a un tableau vian des proprietees.


    Note : J'ai oublié de te dire un truc sur les property : les definition Read et Write sont optionnelles ... c'ets a dire que si il manque la property Write (90% Des cas) la variable ne peut etre affactée et donc protege le menbre privé de toute ecriture externe

    LA puissances des methodes Getter/Setter avec l'aisance d'utilisation d'une variable

  18. #18
    Membre actif Avatar de lun4t1k
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    276
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Janvier 2007
    Messages : 276
    Points : 274
    Points
    274
    Par défaut
    Cool merci, mon record sera TMemoryStream ou TFileStream.
    Aucu tri ne serait nécessaie.
    Je peux donc simplifier ta THashStringList.
    Elle pourrait peut etre me servir.
    Merci

  19. #19
    Modérateur

    Homme Profil pro
    Ingénieur retraité
    Inscrit en
    Octobre 2005
    Messages
    2 396
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur retraité

    Informations forums :
    Inscription : Octobre 2005
    Messages : 2 396
    Points : 3 266
    Points
    3 266
    Par défaut
    D'accord je ferai un comparatif entre TMemoryStream et TFileStream pour orienter mon choix.
    ... le choix risque d'être vite fait :
    - TFileStream : y'a presque rien en mémoire,
    - TMemoryStream : t'as absolument tout dans la Memory,
    ... donc si ta mem-vive-dispo te permet d'y mettre tes 800Mo le TMemoryStream est jouable sinon Exit le TMemoryStream.

    tableaux associatifs
    ... à première vue ça semble compliqué juste pour y stocker temporairement des combinaisons. Si t'as besoin d'accumuler temporairement des combinaisons qui forment des string tu peux utiliser des StringList c'est vachement souple d'utilisation :
    maStringList.Add('maChaine');
    maStringLis.AddStrings(maDeuxiemeStringList);
    maStringList.Insert(Indice,'maChaine');
    maStringList.Delete(Indice);
    et en lien avec les Stream's :
    maStringList.SaveToStream(monStream1);
    monStream2.CopyFrom(monStream1,monStream1.Size);
    et pour la suite :
    monStream2.write(const Buffer; Count: Longint): Longint
    A+
    P.S : j'avais pas remarqué que des messages s'étaient intcarlés avant que j'aie terminé.

  20. #20
    Membre actif Avatar de lun4t1k
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    276
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Janvier 2007
    Messages : 276
    Points : 274
    Points
    274
    Par défaut
    Clorish

    Merci de l'explication.
    Ce soir j'implémente mon tab associatif,
    j'essaie d'enregistrer mes 500fichiers et je reviendrais vous voir.

    Est il nécessaire de marquer résolu?
    Sachant qu'un retour de ma part sera probable?
    je veux faire mon devoir de 'forum-citoyen' !

Discussions similaires

  1. Script pour manipuler une chaine d'un nom de fichier
    Par mond14 dans le forum Shell et commandes GNU
    Réponses: 6
    Dernier message: 23/05/2013, 20h37
  2. Manipulation d'une liste chainée en C++
    Par id_rima dans le forum C++
    Réponses: 11
    Dernier message: 21/06/2010, 10h50
  3. manipulation d'une liste chainé
    Par sorari dans le forum C++
    Réponses: 1
    Dernier message: 16/03/2005, 12h32

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