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 :

OutOfMemoryError with TStringList


Sujet :

Delphi

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Homme Profil pro
    Ressources humaines
    Inscrit en
    Mars 2014
    Messages
    12
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France

    Informations professionnelles :
    Activité : Ressources humaines

    Informations forums :
    Inscription : Mars 2014
    Messages : 12
    Par défaut OutOfMemoryError with TStringList
    Bonjour,

    j'essaye de remplir une stringlist avec un streamreader.
    Mais j'ai un OutOfMemoryError quand j'ajoute les lignes.
    J'ai déja chercher beaucoup sur le web mais n'ai pas trouvé de solution.
    J'ai aussi augmenté la capacité de la stringlist avec capacity mais cela n'a rien changé.
    Merci pour votre aide.

    Voici mon code:

    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
    list := TStringList.create;
    //list.Capacity := 100000000; ne marche pas
    Reader := TStreamReader.Create(filename, true);
    try
    list.BeginUpdate;
    try
    list.Clear;
    while not Reader.EndOfStream do
    list.Add(Reader.ReadLine); > OutOfMemoryError
    finally
    list.EndUpdate;
    end;
    finally
    Reader.Free;
    end;
    J'ai oublié de le dire, mon fichier est un fichier XML qui fait 250 MO.

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

    Informations professionnelles :
    Activité : Expert Delphi

    Informations forums :
    Inscription : Mars 2006
    Messages : 1 539
    Billets dans le blog
    10
    Par défaut
    Bonjour,
    En complément d'information XML an ANSI ou UNICODE
    Quelle version de Delphi ?

  3. #3
    Membre averti
    Homme Profil pro
    Ressources humaines
    Inscrit en
    Mars 2014
    Messages
    12
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France

    Informations professionnelles :
    Activité : Ressources humaines

    Informations forums :
    Inscription : Mars 2014
    Messages : 12
    Par défaut
    DELPHI XE
    UTF-8

  4. #4
    Expert éminent
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    14 086
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    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 : 14 086
    Par défaut
    100 000 000 lignes !
    Dans le sujet La question du 12h55 sur TList , on avait échangé sur la limite à 134 217 728 éléments dans une TStringList ou une TList

    Sinon 100 000 000 lignes et 250 Mo (250 000 000 o)
    ça ne fait que 25 octet par ligne, c'est juste, surtout sur un XML avec un tas d'espace pour qu'il soit lisible

    Dans mon XE2, la TStringList a été réécrite et n'a plus de limite explicite (MaxListSize est deprecated)
    mais sur Win32, tu ne pourras pas dépasser ce nombre à cause que tu ne peux pas allouer plus de 2Go pour une seule variable, et même 2Go pour tout le processus (quoi que cela peut monter à 3Go en bidouillant)
    Voir TMemoryStream : incompréhension

    une chaine vide, c'est quand même un pointeur qui pointe sur nil donc 4 octet, donc au plus 500 millions de pointeurs
    et une chaine d'un caractère ça doit prendre 18 octets à cause de pointeur lui même 4 octets,
    le caractère 2 octets (XE8 donc Unicode), la taille de la chaine 4 octet, le compteur de référence 4 Octet,
    le CodePage et la taile du char encore 4 octets

    Pour une chaine de 25 caractères en Unicode, donc 50 octets + 12 octets de méta data + 4 octet de pointeur = 66 octets
    66 * 100 000 000 = 660 000 000, moins de 2Go ça devrait tenir

    Sur Win64, ça doit pouvoir aller plus loin, mais ça consomme plus pour les 8 octets de pointeur donc 700 000 000 Mo

    tu pouvais directement faire

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    list := TStringList.create;
    try
      list.LoadFromFile(filename);
     
      ... balayer ...
    finally
      list .Free;
    end;
    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

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

    Informations professionnelles :
    Activité : Expert Delphi

    Informations forums :
    Inscription : Mars 2006
    Messages : 1 539
    Billets dans le blog
    10
    Par défaut Un petit exemple en XE7 comme base de travail
    Voilà un petit programme qui marche sur ma machine MS-Windows 8.1 avec un fichier de 255 Mo qui peut te servir comme base de travail.

    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
     
    procedure TForm1.Button1Click(Sender: TObject);
    const
      K1 = $3FFFFF ;
    var
      ms1: TMemoryStream ;
      sl1 : TStringList ;
      st1 : AnsiString ;
      pb1 : ^Byte ;
      i1 : integer ;
    begin
      st1 := 'ABCDEFABCDEFABCDEFABCDEFABCDEFABCDEFABCDEFABCDEFABCDEFABCDEFAB'#13#10 ;
      pb1 := @st1[1] ;
      ms1 := TMemoryStream.create;
      ms1.SetSize(K1*$40);
      for i1 := 1 to K1 do
        ms1.Write(pb1^,64);
      ms1.SaveToFile('X.TXT');
      ms1.Free;
      application.Terminate ;
    end;
     
    procedure TForm1.Button2Click(Sender: TObject);
    var
      sl1 : TStringList ;
      ms1: TMemoryStream ;
    begin
      ms1 := TMemoryStream.create;
      ms1.LoadFromFile('X.TXT');
      sl1 := TStringList.create ;
      sl1.LoadFromStream(ms1);
      sl1.Free;
      ms1.Free;
      application.Terminate ;
    end;

  6. #6
    Membre Expert

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2007
    Messages
    3 527
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 63
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Novembre 2007
    Messages : 3 527
    Par défaut
    Juste par curiosité:

    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
     
    var
      List: TStrings;
      Reader: TStreamReader;
      Filename: string;
      S, P: string;
    begin
      List := TStringList.create;
      Filename := 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxx';  // << à modifier évidemment
      Reader := TStreamReader.create(Filename, true);
      try
        List.BeginUpdate;
        try
          List.Clear;
          while not Reader.EndOfStream do
            try
              P := 'Reader.ReadLine';
              S := Reader.ReadLine;
              P := 'List.Add';
              List.Add(Reader.ReadLine);
            except
              on E: Exception do
                ShowMessage(P);
            end;
        finally
          List.EndUpdate;
        end;
      finally
        Reader.Free;
      end;
    ça donne quoi ??

    Ensuite, le même test sans utiliser beginupdate/endupdate ...

    ps: Je le ferais volontiers moi-même mais je n'ai ton fichier sous la main

Discussions similaires

  1. installation php avec option --with-pgsql: marche pô.
    Par phil25 dans le forum Requêtes
    Réponses: 3
    Dernier message: 02/01/2004, 15h59
  2. [Tstringlist] Retrouvez la liste....
    Par remixtech dans le forum Langage
    Réponses: 7
    Dernier message: 25/06/2003, 23h05
  3. Comment bien gerer la mémoire avec les TStringList?
    Par david_chardonnet dans le forum Langage
    Réponses: 5
    Dernier message: 18/06/2003, 09h57
  4. TStringList en array of string
    Par JediKerian dans le forum Langage
    Réponses: 2
    Dernier message: 20/03/2003, 15h37
  5. TStringList
    Par giaco dans le forum Composants VCL
    Réponses: 3
    Dernier message: 17/09/2002, 13h50

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