2016-06-09 2 views
4

J'ai un très gros fichier, de presque 2Go. J'essaie d'écrire un processus pour lire le fichier et l'écrire sans la première ligne. J'ai à peu près été capable de lire et d'écrire une ligne à la fois, ce qui prend une éternité. Je peux l'ouvrir, enlever la première ligne et l'enregistrer plus rapidement dans TextPad, même si c'est encore très lent.Lecture et écriture de très gros fichiers texte en C#

J'utiliser ce code pour obtenir le nombre d'enregistrements dans le fichier:

private long getNumRows(string strFileName) 
{ 
    long lngNumRows = 0; 
    string strMsg; 

    try 
    { 
     lngNumRows = 0; 
     using (var strReader = File.OpenText(@strFileName)) 
     { 
      while (strReader.ReadLine() != null) 
      { 
       lngNumRows++; 
      } 

      strReader.Close(); 
      strReader.Dispose(); 
     } 
    } 
    catch (Exception excExcept) 
    { 
     strMsg = "The File could not be read: "; 
     strMsg += excExcept.Message; 
     System.Windows.MessageBox.Show(strMsg); 
     //Console.WriteLine("Thee was an error reading the file: "); 
     //Console.WriteLine(excExcept.Message); 

     //Console.ReadLine(); 
    } 

    return lngNumRows; 
} 

Cela ne prend que quelques secondes pour exécuter. Lorsque j'ajoute le code suivant, il faut une éternité pour l'exécuter. Est-ce que je fais quelque chose de mal? Pourquoi l'écriture ajoute-t-elle autant de temps? Des idées sur comment je peux faire ça plus vite?

Non
private void ProcessTextFiles(string strFileName) 
{ 
    string strDataLine; 
    string strFullOutputFileName; 
    string strSubFileName; 
    int intPos; 
    long lngTotalRows = 0; 
    long lngCurrNumRows = 0; 
    long lngModNumber = 0; 
    double dblProgress = 0; 
    double dblProgressPct = 0; 
    string strPrgFileName = ""; 
    string strOutName = ""; 
    string strMsg; 
    long lngFileNumRows; 

    try 
    { 
     using (StreamReader srStreamRdr = new StreamReader(strFileName)) 
     { 
      while ((strDataLine = srStreamRdr.ReadLine()) != null) 
      { 
       lngCurrNumRows++; 

       if (lngCurrNumRows > 1) 
       { 
        WriteDataRow(strDataLine, strFullOutputFileName); 
       } 
      } 

      srStreamRdr.Dispose(); 
     } 
    } 
    catch (Exception excExcept) 
    { 
     strMsg = "The File could not be read: "; 
     strMsg += excExcept.Message; 
     System.Windows.MessageBox.Show(strMsg); 
     //Console.WriteLine("The File could not be read:"); 
     //Console.WriteLine(excExcept.Message); 
    } 
} 

public void WriteDataRow(string strDataRow, string strFullFileName) 
{ 
    //using (StreamWriter file = new StreamWriter(@strFullFileName, true, Encoding.GetEncoding("iso-8859-1"))) 
    using (StreamWriter file = new StreamWriter(@strFullFileName, true, System.Text.Encoding.UTF8)) 
    { 
     file.WriteLine(strDataRow); 
     file.Close(); 
    } 
} 
+6

Ouverture et fermeture du fichier de sortie pour chaque ligne que vous voulez écrire ne contribue pas à – Steve

+0

comme le dit steve et l'exemple précédent ne fait rien écrit des lignes – kenny

+0

Pourquoi avez-vous besoin de compter le nombre de lignes? Ne peux-tu pas compter les lignes et abandonner le premier en un coup? – BugFinder

Répondre

7

sûr combien cela va améliorer les performances, mais sûrement, l'ouverture et la fermeture du fichier de sortie pour chaque ligne que vous voulez écrire n'est pas une bonne idée.

ouvrir lieu les deux fichiers une seule fois, puis écrire la ligne directement

using (StreamWriter file = new StreamWriter(@strFullFileName, true, System.Text.Encoding.UTF8)) 
using (StreamReader srStreamRdr = new StreamReader(strFileName)) 
{ 
    while ((strDataLine = srStreamRdr.ReadLine()) != null) 
    { 
     lngCurrNumRows++; 

     if (lngCurrNumRows > 1) 
      file.WriteLine(strDataRow); 
    } 
} 

Vous pouvez également supprimer le contrôle sur lngCurrNumRow simplement faire une lecture vide avant d'entrer dans la boucle while

strDataLine = srStreamRdr.ReadLine(); 
if(strDataLine != null) 
{ 
    while ((strDataLine = srStreamRdr.ReadLine()) != null) 
    { 
      file.WriteLine(strDataRow); 
    } 
} 
0

Selon sur la mémoire de votre machine. Vous pouvez essayer ce qui suit (mon grand dossier était « D: \ savegrp.log » J'ai eu un fichier 2gb frapper à propos) Cette utilisation de la mémoire 6gb quand je l'ai essayé

int counter = File.ReadAllLines(@"D:\savegrp.log").Length; 
Console.WriteLine(counter); 

Il ne dépend de la mémoire disponible. .

File.WriteAllLines(@"D:\savegrp2.log",File.ReadAllLines(@"D:\savegrp.log").Skip(1)); 
Console.WriteLine("file saved"); 
+0

J'ai essayé le File.ReadAllLines mais je n'ai pas assez de mémoire pour ce fichier. – Cass

+0

Merci Steve, cela a fonctionné comme un charme. Cela m'a pris presque une heure et avec le fichier. WriteLine (strDataRow); cela ne prend que quelques minutes. Merci à tous pour les réponses rapides! – Cass

+0

L'avez-vous compilé en 64 bits? mon peu plus de 2 Go de mon utilisation de la mémoire est allé jusqu'à 6 Go – BugFinder