web-dev-qa-db-fra.com

Lire en grand TXT Fichier, exception de mémoire insuffisante

Je veux lire un gros fichier TXT de 500 Mo, D'abord, je l'utilise 

var file = new StreamReader(_filePath).ReadToEnd();  
var lines = file.Split(new[] { '\n' });

mais cela jette à court d’exception de mémoire puis j’ai essayé de lire ligne par ligne, mais après avoir lu environ 1,5 million de lignes, il jette à court de mémoire

  using (StreamReader r = new StreamReader(_filePath))
         {            
             while ((line = r.ReadLine()) != null)            
                 _lines.Add(line);            
         }

ou j'ai utilisé 

  foreach (var l in File.ReadLines(_filePath))
            {
                _lines.Add(l);
            }

mais encore une fois j'ai reçu 

Une exception de type 'System.OutOfMemoryException' s'est produite dans mscorlib.dll mais n'a pas été traité dans le code utilisateur

Ma machine est une machine puissante avec 8 Go de RAM, ce ne devrait donc pas être mon problème de machine.

p.s: J'ai essayé d'ouvrir ce fichier dans NotePadd ++ et j'ai reçu une exception 'le fichier est trop gros pour être ouvert'.

15
Behnam

Utilisez simplement File.ReadLines qui renvoie un IEnumerable<string> et ne charge pas toutes les lignes en même temps dans la mémoire.

foreach (var line in File.ReadLines(_filePath))
{
    //Don't put "line" into a list or collection.
    //Just make your processing on it.
}
33
L.B

La cause de l'exception semble être la collection _lines croissante mais pas la lecture de gros fichiers Vous lisez la ligne et adding to some collection _lines which will be taking memory and causing out of memory execption. Vous pouvez appliquer des filtres pour ne placer que les lignes requises dans la collection _lines. 

3
Adil

Modifier:

le chargement de tout le fichier en mémoire entraînera la croissance des objets, et .net lancera des exceptions de MOO s'il ne peut pas allouer suffisamment de mémoire contiguë pour un objet.

La réponse est toujours la même, vous devez diffuser le fichier, pas lire le contenu entier. Cela peut nécessiter une nouvelle architecture de votre application. Toutefois, avec les méthodes IEnumerable<>, vous pouvez empiler des processus d’entreprise dans différents domaines de l’application et différer le traitement.


Une machine "puissante" avec 8 Go de RAM ne pourra pas stocker un fichier de 500 Go en mémoire, car 500 est plus grand que 8 (en plus, vous n'obtenez pas 8 car le système d'exploitation tiendra en attente certains, vous ne pouvez pas allouer toute la mémoire en .Net, 32-bit a une limite de 2 Go, l'ouverture du fichier et le stockage de la ligne contiendront les données deux fois, il y a une surcharge de la taille de l'objet ....)

Vous ne pouvez pas charger le tout en mémoire pour le traiter, vous devrez diffuser le fichier en continu tout au long de votre traitement.

1
cjk

Vous devez compter les lignes en premier. C'est plus lent, mais vous pouvez lire jusqu'à 2 147 483 647 lignes.

int intNoOfLines = 0;
using (StreamReader oReader = new 
StreamReader(MyFilePath))
{
    while (oReader.ReadLine() != null) intNoOfLines++;
}
string[] strArrLines = new string[intNoOfLines];
int intIndex = 0;
using (StreamReader oReader = new 
StreamReader(MyFilePath))
{
    string strLine;
    while ((strLine = oReader.ReadLine()) != null)
    {
       strArrLines[intIndex++] = strLine;
    }
}
0
Martin Bächtold