Question

Existe-t-il un moyen simple de déterminer par programme le nombre de lignes d’un fichier texte?

Était-ce utile?

La solution

Modification sérieusement tardive: si vous utilisez .NET 4.0 ou version ultérieure

La classe File a une nouvelle ReadLines est une méthode qui énumère paresseusement les lignes plutôt que de les lire avec avidité dans un tableau comme ReadAllLines . Alors maintenant, vous pouvez avoir à la fois efficacité et concision avec:

var lineCount = File.ReadLines(@"C:\file.txt").Count();

Réponse originale

Si l'efficacité ne vous préoccupe pas trop, écrivez simplement:

var lineCount = File.ReadAllLines(@"C:\file.txt").Length;

Pour une méthode plus efficace, procédez comme suit:

var lineCount = 0;
using (var reader = File.OpenText(@"C:\file.txt"))
{
    while (reader.ReadLine() != null)
    {
        lineCount++;
    }
}

Modifier: en réponse aux questions relatives à l'efficacité

La raison pour laquelle j'ai dit que la seconde était plus efficace concernait l'utilisation de la mémoire, pas nécessairement la vitesse. Le premier charge l'intégralité du contenu du fichier dans un tableau, ce qui signifie qu'il doit allouer au moins autant de mémoire que la taille du fichier. La seconde boucle simplement une ligne à la fois, de sorte qu'elle ne doit jamais allouer plus d'une mémoire à la fois. Ce n'est pas très important pour les petits fichiers, mais pour les gros fichiers, cela peut poser problème (si vous essayez de trouver le nombre de lignes dans un fichier de 4 Go sur un système 32 bits, par exemple, où il n'y a tout simplement pas assez espace d'adressage en mode utilisateur pour allouer un tableau de cette taille).

En termes de vitesse, je ne m'attendrais pas à ce qu'il y en ait beaucoup. Il est possible que ReadAllLines dispose d’optimisations internes, mais il se peut qu’il doive allouer une énorme quantité de mémoire. J'imagine que ReadAllLines pourrait être plus rapide pour les petits fichiers, mais beaucoup plus lente pour les gros fichiers; La seule façon de le savoir serait de le mesurer avec un chronomètre ou un profileur de code.

Autres conseils

Le plus simple:

int lines = File.ReadAllLines("myfile").Length;

Cela utiliserait moins de mémoire, mais prendrait probablement plus de temps

int count = 0;
string line;
TextReader reader = new StreamReader("file.txt");
while ((line = reader.ReadLine()) != null)
{
  count++;
}
reader.Close();

Si par facile vous entendez des lignes de code faciles à déchiffrer mais par hasard inefficaces?

string[] lines = System.IO.File.RealAllLines($filename);
int cnt = lines.Count();

C’est probablement le moyen le plus rapide de savoir combien de lignes.

Vous pouvez également le faire (en fonction de la mise en mémoire tampon)

#for large files
while (...reads into buffer){
string[] lines = Regex.Split(buffer,System.Enviorment.NewLine);
}

Il existe de nombreuses autres manières, mais l’une de ces solutions est probablement celle avec laquelle vous irez.

Vous pouvez le lire rapidement et incrémenter un compteur. Utilisez simplement une boucle pour incrémenter, sans rien modifier avec le texte.

compte les retours chariot / sauts de ligne. Je crois en Unicode, ils sont toujours 0x000D et 0x000A respectivement. De cette façon, vous pouvez être aussi efficace ou aussi inefficace que vous le souhaitez et décider si vous devez ou non traiter les deux personnages

Une option viable, et que j’ai personnellement utilisée, serait d’ajouter votre propre en-tête à la première ligne du fichier. Je l'ai fait pour un format de modèle personnalisé pour mon jeu. En gros, j’ai un outil qui optimise mes fichiers .obj, élimine la merde dont je n’ai pas besoin, les convertit en une meilleure présentation, puis écrit le nombre total de lignes, faces, normales, sommets et UV de texture sur la toute première ligne. Ces données sont ensuite utilisées par divers tampons de tableau lorsque le modèle est chargé.

Cela est également utile car il vous suffit de parcourir le fichier une seule fois pour le charger, au lieu d’une fois de compter les lignes, puis de lire les données dans les tampons créés.

La lecture d'un fichier en lui-même prend un certain temps. Récupérer le résultat est un autre problème, car vous lisez tout le fichier simplement pour compter le (s) caractère (s) de nouvelle ligne,

À un moment donné, quelqu'un va devoir lire les caractères du fichier, qu'il s'agisse de la structure ou de votre code. Cela signifie que vous devez ouvrir le fichier et le lire en mémoire si le fichier est volumineux, cela risque de poser problème, car la mémoire doit être nettoyée.

Nima Ara a fait une belle analyse. que vous pourriez prendre en considération

Voici la solution proposée, car elle lit 4 caractères à la fois, compte le caractère de saut de ligne et réutilise la même adresse mémoire pour la comparaison de caractères suivante.

private const char CR = '\r';  
private const char LF = '\n';  
private const char NULL = (char)0;

public static long CountLinesMaybe(Stream stream)  
{
    Ensure.NotNull(stream, nameof(stream));

    var lineCount = 0L;

    var byteBuffer = new byte[1024 * 1024];
    const int BytesAtTheTime = 4;
    var detectedEOL = NULL;
    var currentChar = NULL;

    int bytesRead;
    while ((bytesRead = stream.Read(byteBuffer, 0, byteBuffer.Length)) > 0)
    {
        var i = 0;
        for (; i <= bytesRead - BytesAtTheTime; i += BytesAtTheTime)
        {
            currentChar = (char)byteBuffer[i];

            if (detectedEOL != NULL)
            {
                if (currentChar == detectedEOL) { lineCount++; }

                currentChar = (char)byteBuffer[i + 1];
                if (currentChar == detectedEOL) { lineCount++; }

                currentChar = (char)byteBuffer[i + 2];
                if (currentChar == detectedEOL) { lineCount++; }

                currentChar = (char)byteBuffer[i + 3];
                if (currentChar == detectedEOL) { lineCount++; }
            }
            else
            {
                if (currentChar == LF || currentChar == CR)
                {
                    detectedEOL = currentChar;
                    lineCount++;
                }
                i -= BytesAtTheTime - 1;
            }
        }

        for (; i < bytesRead; i++)
        {
            currentChar = (char)byteBuffer[i];

            if (detectedEOL != NULL)
            {
                if (currentChar == detectedEOL) { lineCount++; }
            }
            else
            {
                if (currentChar == LF || currentChar == CR)
                {
                    detectedEOL = currentChar;
                    lineCount++;
                }
            }
        }
    }

    if (currentChar != LF && currentChar != CR && currentChar != NULL)
    {
        lineCount++;
    }
    return lineCount;
}

Vous pouvez voir ci-dessus qu’une ligne est lue caractère par caractère aussi bien par le framework sous-jacent que vous devez lire tous les caractères pour voir le saut de ligne.

Si vous décrivez que c’est fait, baie Nima, vous constaterez que c’est un moyen plutôt rapide et efficace de le faire.

try {
    string path = args[0];
    FileStream fh = new FileStream(path, FileMode.Open, FileAccess.Read);
    int i;
    string s = "";
    while ((i = fh.ReadByte()) != -1)
        s = s + (char)i;

    //its for reading number of paragraphs
    int count = 0;
    for (int j = 0; j < s.Length - 1; j++) {
            if (s.Substring(j, 1) == "\n")
                count++;
    }

    Console.WriteLine("The total searches were :" + count);

    fh.Close();

} catch(Exception ex) {
    Console.WriteLine(ex.Message);
}         

Vous pouvez lancer le wc .exe " exécutable (vient avec UnixUtils et ne nécessite pas d'installation) exécuté en tant que processus externe. Il supporte différentes méthodes de comptage de lignes (comme Unix vs Mac vs Windows).

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top