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 :

Passer une StringGrid dans un MemoryStream


Sujet :

Langage Delphi

  1. #1
    Membre habitué

    Homme Profil pro
    Direction financière et formateur en gestion et contrôle de gestion
    Inscrit en
    Mai 2003
    Messages
    194
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Direction financière et formateur en gestion et contrôle de gestion
    Secteur : Conseil

    Informations forums :
    Inscription : Mai 2003
    Messages : 194
    Points : 127
    Points
    127
    Par défaut Passer une StringGrid dans un MemoryStream
    Bonjour à tous,

    Aujourd'hui je m'essaye au Stream mais je m'embrouille un peu ...
    J'ai une StringGrid de 40 colonnes et plusieurs lignes, j'aimerai la passer dans un MemoryStream mais je me perds un peu sur ce coup là.

    Je pensais passer chaque ligne avec StringGrid.Rows[x].text ... mais je bugue complet
    Vous pouvez me dire comment faire ?

    Ensuite, il faudra que je fasse l'inverse ... passer de la MemoryStream à la StringGrid ...

    ... 1h après ...
    Pour écrire ma StringGrid dans le Stream j'ai fais ceci (non testé). Vous pensez que c'est bon ça ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
         for X := 0 to GridPrincipale do
         begin
            S1:= GridPrincipale.Rows[X].Text;
            Stream.Write(S1,SizeOf(S1));
         end;
     
         Stream.SaveToFile(NomFichier) ;
    Par contre, pour lire le Stream et le passer à la Stringgrid je coince encore. Je cherche un moyen de lire du début à la fin, mais pas de EOF comme avec les fichiers ...

  2. #2
    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 : 55
    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 457
    Points
    28 457
    Par défaut
    aïe !

    tu enregistres dans ton stream l'adresse mémoire de toutes les chaînes...ça n'a strictement aucun intérêt

    la première chose à déterminer c'est le format que tu souhaites avoir dans ton fichier

    tu peux utiliser du JSON, du XML, du DFM mais là manifestement tu veux juste stocker dans un format propriétaire.

    mais pour pouvoir relire ton flux, il va falloir préparer les choses

    1) quelles sont les dimensions du tableau ?

    on va placer en début de flux, deux entiers, le nombre de colonnes et le nombre de lignes
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    begin
      i := GridPrincipale.Cols;
      Stream.Write(i, SizeOf(i));
      i := GridPrincipale.Row;
      Stream.Write(i, SizeOf(i));
    end;
    2) on peut maintenant stocker les valeurs

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    for y := 0 to GridPrincipale.Rows - 1 do
      for x := 0 to GridPrincipale.Cols - 1 do
      begin
        s := GridPincipale.Cells[x, y];
        i := Length(s);
        Stream.Write(i, SizeOf(i));
        if i > 0 then
          Stream.Write(s[1], i * SizeOf(Char));
      end;
    voilà on a maintenant un flux pour un tableau dont on connait les dimensions et pour chaque cellule on a le contenu en précisant sa taille

    la lecture devient presque évidente...lire cols, rows, et pour chaque cellule lire la longueur du texte, puis le texte

  3. #3
    Membre émérite
    Avatar de ALWEBER
    Homme Profil pro
    Expert Delphi
    Inscrit en
    Mars 2006
    Messages
    1 504
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 69
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Expert Delphi

    Informations forums :
    Inscription : Mars 2006
    Messages : 1 504
    Points : 2 776
    Points
    2 776
    Billets dans le blog
    10
    Par défaut
    C'est déjà proposé par Delphi

    Exemple
    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
    function Serialize(O1: TComponent) : string ;
    var
      MS1, MS2: TMemoryStream;
      Sl1: TStringList;
    begin
      MS1 := TMemoryStream.Create;
      MS2 := TMemoryStream.Create;
      Sl1 := TStringList.Create;
      MS1.WriteComponent(O1);
      MS1.Seek(0, soFromBeginning);
      ObjectBinaryToText(MS1, MS2);
      MS2.Seek(0, soFromBeginning);
      Sl1.LoadFromStream(MS2);
      result := sl1.Text ;
      Sl1.Free;
      MS2.Free;
      MS1.Free
    end;
    Tu peux t'en inspirer. Si besoin d'exemple je te l'en envoie un

  4. #4
    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
    Tu peux utiliser un format classique comme le CSV : TStringGridCSVHelper

    un vieux code genre mon TStringGridCrossManager qui exporte un TStringGrid dans un fichier

    Le DFM comme proposé ci-dessus est pertinent aussi, le chargement étant un peu plus délicat sur la gestion de l'instance.

  5. #5
    Membre habitué

    Homme Profil pro
    Direction financière et formateur en gestion et contrôle de gestion
    Inscrit en
    Mai 2003
    Messages
    194
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Direction financière et formateur en gestion et contrôle de gestion
    Secteur : Conseil

    Informations forums :
    Inscription : Mai 2003
    Messages : 194
    Points : 127
    Points
    127
    Par défaut
    En fait c'est un CSV
    Donc ok, le plus simple est de passer par une StringList qui elle à tout ce qu'il faut pour passer par des Stream et les fichiers avec les SaveTo et LoadFrom
    Je m'étais dit que pour gagner du temps dans les boucles je pouvais directement mettre une string représentée par GridPrincipale.Rows[X].Text dans un Stream, mais visiblement celui ci ne se manipule pas comme une StringList ....
    Ou alors il y a quelque chose que je ne connais pas ?

  6. #6
    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
    En Lazarus : lcsvutils.LoadFromCSVFile

    En Delphi :
    Si l'on ne se préoccupe pas des performances, lire et écrire un CSV avec une TStringGrid VCL c'est juste enfantin.
    Si l'on ne préoccupe pas non plus des données multi-lignes, c'est vive fait :


    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
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    unit DirtyStringGrid_MainForm;
     
    interface
     
    uses
      Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
      Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.Grids;
     
    type
      TForm1 = class(TForm)
        Memo1: TMemo;
        StringGrid1: TStringGrid;
        Button1: TButton;
        Button2: TButton;
        Memo2: TMemo;
        procedure Button1Click(Sender: TObject);
        procedure Button2Click(Sender: TObject);
      private
        { Déclarations privées }
      public
        { Déclarations publiques }
      end;
     
      TStringGridTool = record
      public
        class procedure LoadFromStream(AGrid: TStringGrid; AStream: TStream); static;
        class procedure SaveToStream(AGrid: TStringGrid; AStream: TStream); static;
      end;
     
    var
      Form1: TForm1;
     
    implementation
     
    uses System.Math;
     
    {$R *.dfm}
     
    procedure TForm1.Button1Click(Sender: TObject);
    var
      MS: TMemoryStream;
    begin
      MS := TMemoryStream.Create();
      try
        Memo1.Lines.SaveToStream(MS);
     
        MS.Seek(0, soBeginning);
        TStringGridTool.LoadFromStream(StringGrid1, MS);
      finally
        MS.Free();
      end;
    end;
     
    procedure TForm1.Button2Click(Sender: TObject);
    var
      MS: TMemoryStream;
    begin
      MS := TMemoryStream.Create();
      try
        TStringGridTool.SaveToStream(StringGrid1, MS);
     
        MS.Seek(0, soBeginning);
        Memo2.Lines.LoadFromStream(MS);
      finally
        MS.Free();
      end;
    end;
     
    { TStringGridTool }
     
    class procedure TStringGridTool.LoadFromStream(AGrid: TStringGrid; AStream: TStream);
    var
      Lines, Header: TStringList;
      I: Integer;
    begin
      Lines := TStringList.Create();
      try
        Lines.LoadFromStream(AStream);
     
        AGrid.FixedRows := 1; // Header ?
        AGrid.RowCount := Lines.Count;
        AGrid.FixedCols := 0;
        AGrid.ColCount := 0;
     
        if Lines.Count > 0 then
        begin
          Header := TStringList.Create();
          try
            Header.Delimiter := ';';
            Header.StrictDelimiter := True;
            Header.DelimitedText := Lines[0];
            AGrid.ColCount := Header.Count;
     
            AGrid.Rows[0].Assign(Header);
          finally
            Header.Free();
          end;
     
          for I := 1 to Lines.Count - 1 do
          begin
            AGrid.Rows[I].Delimiter := ';';
            AGrid.Rows[I].StrictDelimiter := True;
            AGrid.Rows[I].DelimitedText := Lines[I];
     
            AGrid.ColCount := Max(AGrid.ColCount, AGrid.Rows[I].Count);
          end;
        end;
      finally
        Lines.Free();
      end;
    end;
     
    class procedure TStringGridTool.SaveToStream(AGrid: TStringGrid; AStream: TStream);
    var
      Lines: TStringList;
      I: Integer;
    begin
      Lines := TStringList.Create();
      try
        Lines.Capacity := AGrid.RowCount;
     
        for I := 0 to AGrid.RowCount - 1 do
        begin
          AGrid.Rows[I].Delimiter := ';';
          Lines.Add(AGrid.Rows[I].DelimitedText);
        end;
     
        Lines.SaveToStream(AStream);
      finally
        Lines.Free();
      end;
    end;
     
    end.
    Evidemment TMemo et TMemoryStream c'est pour faire un démo simpliste à remplacer par un TFileStream

    et la DFM :

    Code DFM : 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
    object Form1: TForm1
      Left = 0
      Top = 0
      Caption = 'Form1'
      ClientHeight = 522
      ClientWidth = 710
      Color = clBtnFace
      Font.Charset = DEFAULT_CHARSET
      Font.Color = clWindowText
      Font.Height = -11
      Font.Name = 'Tahoma'
      Font.Style = []
      OldCreateOrder = False
      PixelsPerInch = 96
      TextHeight = 13
      object Memo1: TMemo
        Left = 574
        Top = 8
        Width = 128
        Height = 86
        Lines.Strings = (
          'A;B;C'
          '1;2;3'
          '4;5;6'
          '7;8;9')
        TabOrder = 0
      end
      object StringGrid1: TStringGrid
        Left = 8
        Top = 8
        Width = 467
        Height = 434
        TabOrder = 1
      end
      object Button1: TButton
        Left = 481
        Top = 69
        Width = 75
        Height = 25
        Caption = 'Button1'
        TabOrder = 2
        OnClick = Button1Click
      end
      object Button2: TButton
        Left = 481
        Top = 100
        Width = 75
        Height = 25
        Caption = 'Button2'
        TabOrder = 3
        OnClick = Button2Click
      end
      object Memo2: TMemo
        Left = 574
        Top = 100
        Width = 128
        Height = 142
        Lines.Strings = (
          'Memo2')
        TabOrder = 4
      end
    end

  7. #7
    Membre habitué

    Homme Profil pro
    Direction financière et formateur en gestion et contrôle de gestion
    Inscrit en
    Mai 2003
    Messages
    194
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Direction financière et formateur en gestion et contrôle de gestion
    Secteur : Conseil

    Informations forums :
    Inscription : Mai 2003
    Messages : 194
    Points : 127
    Points
    127
    Par défaut
    ShaiLeTroll là ma curiosité est piquée

    En Delphi :
    Si l'on ne se préoccupe pas des performances, ...
    Actuellement, je fais ceci pour passer d'une StringList dans laquelle j'ai chargé mon Stream vers une StringGrid

    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
     
      List_Transfert_Enregistrement:=TStringList.Create();
     
      Stream :=TMemoryStream.Create ;
      Stream.LoadFromFile(NomFichier);
      ...// traitement dans le TmemoryStream ...
      List_Transfert_Enregistrement.LoadFromStream(Stream);
     
      for X := 0 to GridDestination.RowCount - 1
      do Principale.GridPrincipale.Rows[X].Clear;
      GridDestination.RowCount := 1;
     
      for X := 0 to List_Transfert_Enregistrement.Count - 1 do
      begin
         if trim(List_Transfert_Enregistrement[X])<>''
         then begin
            GridDestination.Rows[GridDestination.RowCount - 1].QuoteChar := FQuoteChar;
            GridDestination.Rows[GridDestination.RowCount - 1].Delimiter := FSVdelimiter;
            GridDestination.Rows[GridDestination.RowCount - 1].StrictDelimiter := true;
            GridDestination.Rows[GridDestination.RowCount - 1].DelimitedText := List_Transfert_Enregistrement[X];
            GridDestination.RowCount := GridDestination.RowCount + 1;
         end;
      end;
    TStringGridTool.LoadFromStream(StringGrid1, MS);
    Serait-il plus rapide ?

    Tiens, j'ai droit à un
    TStringGridTool "Directive inconnue"

  8. #8
    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
    C'est en fait la même chose ... à la seule différence de la gestion de ligne vide.
    Avant de poser la question si cela serait plus rapide, avez-vous lu le code ?
    En voyant que cela utilisait DelimitedText, vous auriez eu la réponse immédiatement.

    faire un with aura l'avantage de ne pas recalculer Rows[] 4 fois, c'est un gain mineur mais il existe tout de même, c'est d'ailleurs applicable aussi dans TStringGridTool

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    with GridDestination.Rows[GridDestination.RowCount - 1] do
    ...


    Sinon TMemoryStream.LoadFromFile + TStringList.LoadFromStream pour lire un fichier double la consommation mémoire, un TStringList.LoadFromFile fait très bien le travail .
    Quel est ce traitement évoqué qui nécessite le Stream, est-ce un Dézippage par exemple ? un déchiffrage ?
    Dans ce genre de cas, le passage par le Stream temporaire est pertinent, cependant vous devriez le vider dès qu'il n'est plus utile pour économiser la mémoire.
    je ne vois aucun try finally ... éliminé pour le forum ? ou juste vous ne traitez pas les cas d'exception ?


    Pour le message "Directive inconnue", vous n'avez pas correctement recopié le code fourni.



    Pourquoi ne pas avoir fourni ce code dès le début ?
    Toutes les personnes ayant répondu à votre message ont perdu du temps dans de fausses pistes.

  9. #9
    Membre habitué

    Homme Profil pro
    Direction financière et formateur en gestion et contrôle de gestion
    Inscrit en
    Mai 2003
    Messages
    194
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Direction financière et formateur en gestion et contrôle de gestion
    Secteur : Conseil

    Informations forums :
    Inscription : Mai 2003
    Messages : 194
    Points : 127
    Points
    127
    Par défaut
    Merci pour la réponse ShaiLeTroll
    ... en fait oui, le Stream c'est pour du cryptage/décryptage avec l'unité https://www.developpez.net/forums/d1...e-epilogue-2-a

    Oui ce stream est détruit instantanément.

    Ah, je ne savais pas que le faisait gagner du temps de calcul ... du coup je l'occultait soigneusement, préférant une lisibilité de mon code ... ok, je revois mon jugement.

    Pour le message d'erreur, ... rien, je m'étais arrêté à l'entête de ton code pensant que c'était une classe dérivée... du coup évidemment les records sans codes derrières ...

    Pourquoi ne pas avoir fourni ce code dès le début ?
    Toutes les personnes ayant répondu à votre message ont perdu du temps dans de fausses pistes.
    Parce qu'au début je pensais traiter la chose plus directement, comme dit dans le titre, et j'ai fourni l'idée du code du moment. C'est en tâtonnant, en regardant des solutions proposées ici et dans d'autres discutions que le code est arrivé là où il est.

    Maintenant je cherche à gagner le plus de vitesse possible ... la requête étant redondante.

  10. #10
    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
    Pour gagner en performance, on va vous proposer des solutions à base de pointeurs avec des fonctions de Explose\Implode maison remplaçant le parsage bête et méchant d'une TStringList.

    Vu votre difficulté à votre premier message avec le fait que les string sont des références sur un type complexe de la forme [Header][Len]Data[ZT] avec le @[1] qui pointe sur Data, le reste étant masqué (cf StrRec), j'ai quelques doutes à vous proposer des méthodes de programmation un peu plus hardues.

    Sans parler du ".Text" qui n'est pas plus performant qu'un DelimitedText, c'est tout aussi couteux car cela concatène les chaines de façon simpliste ... même si avec FastMM on peut maintenant ne plus trop s'en inquiéter.
    Le problème c'est que cela stocke toutes les valeurs vides, alors qu'un travail d'élimination de la valeur vide serait un gain si le cas est fréquent.

    Manipuler une TStringGrid ne sera jamais performant, tout ce qui est affichage est lent par définition.
    Même en passant par un TClientDataSet + TDBGrid, le remplissage du TClientDataSet ne sera pas forcément plus rapide et sera inévitable très consommateur en RAM.

    Au final, le format de fichier CSV, c'est un choix ou un hasard de la discussion, car au début on pouvait penser à un format binaire maison et dans ce cas j'ai déjà fourni une approche dans ce sens : TStringGridCrossManager conçu en D7 donc Ansi à corriger pour gérer de l'UTF8 ou de l'Unicode, l'un plus lent à encoder\décoder, le second plus volumineux.

  11. #11
    Membre habitué

    Homme Profil pro
    Direction financière et formateur en gestion et contrôle de gestion
    Inscrit en
    Mai 2003
    Messages
    194
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Direction financière et formateur en gestion et contrôle de gestion
    Secteur : Conseil

    Informations forums :
    Inscription : Mai 2003
    Messages : 194
    Points : 127
    Points
    127
    Par défaut
    Effectivement ... et mon niveau en Delphi ne me permettra pas d'atteindre un niveau tel que les vôtres (je m'adresse à vous les pros de la prog).
    Il est vrai que la grille principale qui contient les données n'est finalement qu'un conteneur facile à exploiter par les fonctions [Col, Row]. Un composant non visuel mais possédant cette facilité serait tout aussi valable puisque l'utilisateur ne voit pas cette grille.
    Ce conteneur ne sert finalement que d'interface entre le fichier qui les stocke sur le disque et le logiciel qui exploite les données contenues.
    (... preneur d'idées si jamais ...)

    Le CSV a été un choix (facilité d'exploitation, standard)
    Ce n'est pas le plus rapide, c'est vrai, mais bon, une fois dans la grille, plus trop de soucis, on est pas au 1/4 de seconde non plus.

    Maintenant le chiffrage est demandé, on perd le coté standard du csv, mais pas le choix dans cette affaire.

    Bon, ça tourne plutôt bien, je pensais trouver une forme plus rapide mais au final ce n'est pas si lent que ça.
    Maintenant je suis en train de me dire que je pourrais utiliser une compression des données ... aventure dans le TZipFile, qui pose déjà des soucis vu le peu d'explication que je trouve ... nouveau post en vue ...

    Dans tous les cas, merci à tous de votre bienveillance vis à vis des non pro de la prog (moi ) et de vos lumières.

  12. #12
    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
    Si c'est un composant interne, rien de plus simple qu'un simple array[] of array[] of string ou encore un TObjectList of TStringList, plutôt orienté Ligne comme premier indice et colonne comme second indice.

    Le CSV à l'avantage d'être simple et classique.
    Avez-songé à un import du CSV dans une table d'une base de données, le CSV peut s'importer en masse facilement via des composants DB, ne serait que ADO, BatchMove voir des imports Bulk interne au SGBD.

  13. #13
    Membre expert
    Avatar de pprem
    Homme Profil pro
    MVP Embarcadero - formateur&développeur Delphi, PHP et JS
    Inscrit en
    Juin 2013
    Messages
    1 876
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loiret (Centre)

    Informations professionnelles :
    Activité : MVP Embarcadero - formateur&développeur Delphi, PHP et JS
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Juin 2013
    Messages : 1 876
    Points : 3 614
    Points
    3 614
    Par défaut
    C'est peut-être une question conne, mais pourquoi un TMemoryStream plutôt qu'un TStringStream fait pour gérer justement des chaînes de caractère et leur encodage ?

    Le transfert d'un stream à un autre est ensuite assez simple à faire (suffit de stocker le type de stream, sa taille, puis son contenu).

    Si tu pars d'une grille, tu ajoutes les coordonnées de la cellule concernée et c'est réglé.

  14. #14
    Rédacteur/Modérateur

    Avatar de SergioMaster
    Homme Profil pro
    Développeur informatique retraité
    Inscrit en
    Janvier 2007
    Messages
    15 119
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 68
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 119
    Points : 41 252
    Points
    41 252
    Billets dans le blog
    63
    Par défaut
    Citation Envoyé par patrice@ Voir le message
    Il est vrai que la grille principale qui contient les données n'est finalement qu'un conteneur facile à exploiter par les fonctions [Col, Row]. Un composant non visuel mais possédant cette facilité serait tout aussi valable puisque l'utilisateur ne voit pas cette grille.
    Ce conteneur ne sert finalement que d'interface entre le fichier qui les stocke sur le disque et le logiciel qui exploite les données contenues.
    Le CSV a été un choix (facilité d'exploitation, standard)
    Maintenant le chiffrage est demandé, on perd le coté standard du csv, mais pas le choix dans cette affaire.
    Bon, je mets mon grain de sel un peu tard.
    Les points mis en gras m'interpellent.

    Il n'aurait pas été plus simple d'utiliser une table mémoire (je pense à FDMemtable) ?

    Maintenant le chiffrage est demandé,
    Le chiffrage entre quoi et quoi ? Le chiffrage des données sur le poste de l'utilisateur, le chiffrage de la transmission des données entre le serveur de BDD et le poste, ou la transmission entre les deux ?
    La solution dépend de la réponse et du type de SGBD, AMHA.
    Cela dépend également du process mis en place :
    - envoi de CSV à partir du serveur - rapatriement et traitement de CSV
    - récupération de données directement - rapatriement et traitement de CSV par la suite
    - ???

  15. #15
    Membre habitué

    Homme Profil pro
    Direction financière et formateur en gestion et contrôle de gestion
    Inscrit en
    Mai 2003
    Messages
    194
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Direction financière et formateur en gestion et contrôle de gestion
    Secteur : Conseil

    Informations forums :
    Inscription : Mai 2003
    Messages : 194
    Points : 127
    Points
    127
    Par défaut
    Ouah, j'ai de la chance que vous vous penchiez sur mon truc.

    Bonjour SergioMaster,
    non non, pas un peu tard, bien au contraire, c'est toujours un plaisir

    Il n'aurait pas été plus simple d'utiliser une table mémoire (je pense à FDMemtable) ?
    Ah ben je ne connais que la StringGrid pour faire des grilles ... Ah si, les tableaux ... je n'avait pas pensé aux tableaux ... FDMemTable, je me penche dessus pour voir ce que c'est

    Le chiffrage entre quoi et quoi ?
    Le fichier enregistré ne doit pas être modifiable de l'extérieur d’où le chiffrage avant enregistrement sur le disque. J'utilise l'unité à laquelle tu as contribué (j'ai cité le lien plus haut)

    Bonjour Prem
    C'est peut-être une question conne, mais pourquoi un TMemoryStream plutôt qu'un TStringStream
    Heu non pas conne du tout. En fait, en lisant les consignes données pour l'utilisation de l'unité de cryptage, Rekin85 utilise un TMemoryStream. Je ne me suis pas posé plus de question ...

    Bonjour ShaiLeTroll
    Avez-songé à un import du CSV dans une table d'une base de données
    Heuuu ... nooonnnn. Je gagnerai en vitesse?

    Ce que j'ai trouvé de bien dans ce composant Grid c'est sa simplicité d'accès par [Col,Row], mais c'est tout.
    Par contre, quand je fais des recherches sur une info, le balayage de la grille peut effectivement prendre du temps ... je n'avais pas trop pensé à ça
    Ce qu'il y a dans cette Grille (nommée GridPrincipale) ? Et bien juste des dates, des chiffres, du texte. Rien de particulier.

    Pour vous qui utilisez Delphi en pro, j'aurais à gagner à utiliser d'autres méthodes par rapport à une TStringGrid ? (mis à par la taille mangée par ce composant, parce que j'imagine bien qu'il prend plus de place qu'un tableau)

  16. #16
    Rédacteur/Modérateur

    Avatar de SergioMaster
    Homme Profil pro
    Développeur informatique retraité
    Inscrit en
    Janvier 2007
    Messages
    15 119
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 68
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 119
    Points : 41 252
    Points
    41 252
    Billets dans le blog
    63
    Par défaut
    Citation Envoyé par patrice@ Voir le message
    J'utilise l'unité à laquelle tu as contribué (j'ai cité le lien plus haut)
    Euh, non, le seul lien que je vois de cité, je n'y ai pas participé

    Citation Envoyé par patrice@ Voir le message
    Ah ben je ne connais que la StringGrid pour faire des grilles ... Ah si, les tableaux ... je n'avait pas pensé aux tableaux ...
    FDMemTable, je me penche dessus pour voir ce que c'est
    Déjà, pour du non visuel un tableau eu été mieux.
    Maintenant, le FDMemTable ce n'est ni plus ni moins qu'une table de base de donnée (en fait SQLite) en mémoire, c'est un peu ce que voulait dire ShaiLeTroll avec sa phrase
    un import du CSV dans une table d'une base de données
    je pense.
    Citation Envoyé par patrice@ Voir le message
    Par contre, quand je fais des recherches sur une info,
    Là, la FDmemTable (avec Locate ou FindKey) voire, bien que plus complexe à la mise en oeuvre, du FDLocalQuery résoudrai ça.

    Citation Envoyé par patrice@ Voir le message
    Le fichier enregistré ne doit pas être modifiable de l'extérieur d’où le chiffrage avant enregistrement sur le disque.
    je ne comprends toujours pas !

  17. #17
    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
    Il n'y a aucune raison d'utiliser une TStringGrid si c'est pour un traitement mémoire

    Avant de partir sur de choses plus complexes, commencez par la base, la B.A-BA : array of array of string ou TObjectList<TStringList>, ce dernier étant le plus simple pour le parsage.
    Il n'y a pas besoin de composant pour faire un tableau, il y a tout simplement le type tableau



    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
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    { TSimplyCSV }
     
    constructor TSimplyCSV.Create();
    begin
      inherited Create();
     
      FCells := TObjectList<TStringList>.Create();
    end;
     
    destructor TSimplyCSV.Destroy();
    begin
      FreeAndNil(FCells);
     
      inherited Destroy();
    end;
     
    function TSimplyCSV.GetCell(Row, Col: Integer): string;
    begin
      if Row < FCells.Count then
        with FCells[Row] do
          if Col < Count then
            Exit(Strings[Col]);
     
      Result := '';
    end;
     
    function TSimplyCSV.GetRowCount(): Integer;
    begin
      Result := FCells.Count;
    end;
     
    procedure TSimplyCSV.LoadFromStream(AStream: TStream);
    var
      Lines, Line: TStringList;
      I: Integer;
    begin
      Lines := TStringList.Create();
      try
        Lines.LoadFromStream(AStream);
        FCells.Capacity := Lines.Count;
        FColCount := 0;
     
        for I := 0 to Lines.Count - 1 do
        begin
          Line := TStringList.Create();
          Line.StrictDelimiter := True;
          Line.Delimiter := ';';
          Line.DelimitedText := Lines[I];
     
          FCells.Add(Line);
     
          FColCount := Max(FColCount, Line.Count);
        end;
      finally
        Lines.Free();
      end;
    end;
     
    procedure TSimplyCSV.SaveToStream(AStream: TStream);
    var
      Lines: TStringList;
      I: Integer;
    begin
      Lines := TStringList.Create();
      try
        Lines.Capacity := FCells.Count;
     
        for I := 0 to FCells.Count - 1 do
        begin
          FCells[I].Delimiter := ';';
          Lines.Add(FCells[I].DelimitedText);
        end;
     
        Lines.SaveToStream(AStream);
      finally
        Lines.Free();
      end;
    end;
     
    procedure TSimplyCSV.SetCell(Row, Col: Integer; const Value: string);
    var
      I: Integer;
    begin
      for I := FCells.Count to Row do
        FCells.Add(TStringList.Create());
     
      with FCells[Row] do
      begin
        for I := Count to Col do
          Add('');
     
        Strings[Col] := Value;
      end;
    end;



    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
    procedure TForm1.Button3Click(Sender: TObject);
    var
      MS: TMemoryStream;
    begin
      if not Assigned(FSimplyCSV) then
        FSimplyCSV := TSimplyCSV.Create();
     
     
      MS := TMemoryStream.Create();
      try
        Memo1.Lines.SaveToStream(MS);
     
        MS.Seek(0, soBeginning);
        FSimplyCSV.LoadFromStream(MS);
      finally
        MS.Free();
      end;
    end;
     
    procedure TForm1.Button4Click(Sender: TObject);
    var
      MS: TMemoryStream;
    begin
      if not Assigned(FSimplyCSV) then
        FSimplyCSV := TSimplyCSV.Create();
     
      MS := TMemoryStream.Create();
      try
        FSimplyCSV.SaveToStream(MS);
     
        MS.Seek(0, soBeginning);
        Memo2.Lines.LoadFromStream(MS);
      finally
        MS.Free();
      end;
    end;
     
    procedure TForm1.Button5Click(Sender: TObject);
    begin
      if not Assigned(FSimplyCSV) then
        FSimplyCSV := TSimplyCSV.Create();
     
      FSimplyCSV.Cells[1, 2] := 'Modified: ' +  FSimplyCSV.Cells[1, 2];
      FSimplyCSV.Cells[7, 5] := 'Added';
    end;

  18. #18
    Membre habitué

    Homme Profil pro
    Direction financière et formateur en gestion et contrôle de gestion
    Inscrit en
    Mai 2003
    Messages
    194
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Direction financière et formateur en gestion et contrôle de gestion
    Secteur : Conseil

    Informations forums :
    Inscription : Mai 2003
    Messages : 194
    Points : 127
    Points
    127
    Par défaut
    Sergio Master, mince, oui, désolé, c'est Gilbert Geyer qui a participé au projet ... oups

    Oui, c'est vrai, à l'époque de la genèse du projet, je ne me posais pas de question, il fallait que j'avance sur ce projet qui a largement évolué depuis. Et je n'ai jamais remis en cause mes choix de l'époque. Il est temps, et c'est vrai que les tableaux sont là pour ça.
    Je ne vous embête plus avec ça, je profite de vos commentaires pour faire évoluer mon projet.
    Pour moi, le sujet est résolu et plus que ça encore.

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

Discussions similaires

  1. [JDBC]Passer une valeur dans une requete KO
    Par joseph_p dans le forum JDBC
    Réponses: 6
    Dernier message: 16/02/2008, 17h00
  2. passer unee struct dans un buffer (char *)
    Par baert dans le forum C++
    Réponses: 2
    Dernier message: 20/02/2006, 21h49
  3. [VBA]Passer une variable dans une formule Excel
    Par David1974 dans le forum Macros et VBA Excel
    Réponses: 4
    Dernier message: 27/01/2006, 16h52
  4. [Struts] Passer une variable dans l'url
    Par pilz dans le forum Struts 1
    Réponses: 2
    Dernier message: 30/03/2005, 15h23
  5. Sauver une StringGrid dans un fichier
    Par Rodrigue dans le forum C++Builder
    Réponses: 2
    Dernier message: 10/12/2003, 14h52

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