Réponses:
Édition sérieusement tardive: si vous utilisez .NET 4.0 ou version ultérieure
La File
classe a une nouvelle ReadLines
méthode qui énumère paresseusement les lignes plutôt que de les lire avidement 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 vous ne vous souciez pas trop de l'efficacité, vous pouvez simplement écrire:
var lineCount = File.ReadAllLines(@"C:\file.txt").Length;
Pour une méthode plus efficace, vous pouvez faire:
var lineCount = 0;
using (var reader = File.OpenText(@"C:\file.txt"))
{
while (reader.ReadLine() != null)
{
lineCount++;
}
}
Edit: En réponse aux questions sur 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 tout le 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 n'a jamais à allouer plus d'une valeur de mémoire à la fois. Ce n'est pas si important pour les petits fichiers, mais pour les fichiers plus gros, cela pourrait être un 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 en 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 ait quelques optimisations internes, mais d'un autre côté, il devra peut-être allouer une énorme quantité de mémoire. Je suppose que ReadAllLines pourrait être plus rapide pour les petits fichiers, mais beaucoup plus lent pour les gros fichiers; bien que la seule façon de le savoir soit de le mesurer avec un chronomètre ou un profileur de code.
ReadLines().Count()
vous devrez ajouter un using System.Linq
à vos inclusions. Il semblait assez peu intuitif d'exiger cet ajout, c'est pourquoi je le mentionne. Si vous utilisez Visual Studio, cet ajout est probablement effectué automatiquement pour vous.
Si par facilité, vous entendez des lignes de code faciles à déchiffrer mais par chance 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 (selon que vous le mettez en mémoire tampon)
#for large files
while (...reads into buffer){
string[] lines = Regex.Split(buffer,System.Enviorment.NewLine);
}
Il existe de nombreuses autres façons, mais l'une des options ci-dessus 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 faire avec le texte.
La lecture d'un fichier en lui-même prend un certain temps, la récupération du résultat est un autre problème lorsque vous lisez le fichier entier juste pour compter le (s) caractère (s) de nouvelle ligne,
À un moment donné, quelqu'un devra lire les caractères du fichier, que ce soit le framework ou si c'est votre code. Cela signifie que vous devez ouvrir le fichier et le lire dans la mémoire si le fichier est volumineux, cela va potentiellement être un problème car la mémoire doit être récupérée.
Nima Ara a fait une belle analyse que vous pourriez prendre en considération
Voici la solution proposée, car il 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 prochaine comparaison de caractères.
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;
}
Ci-dessus, vous pouvez voir qu'une ligne est lue un caractère à la fois par le cadre sous-jacent, car vous devez lire tous les caractères pour voir le saut de ligne.
Si vous le profilez comme fait baie Nima, vous verriez que c'est un moyen assez rapide et efficace de le faire.
Une option viable, et que j'ai personnellement utilisée, serait d'ajouter votre propre en-tête à la première ligne du fichier. J'ai fait cela pour un format de modèle personnalisé pour mon jeu. Fondamentalement, j'ai un outil qui optimise mes fichiers .obj, se débarrasse de la merde dont je n'ai pas besoin, les convertit en une meilleure mise en page, 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é.
Ceci est également utile car vous n'avez besoin de parcourir le fichier qu'une seule fois pour le charger, au lieu d'une fois pour compter les lignes, et encore pour lire les données dans vos tampons créés.
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 l' exécutable " wc .exe" (livré avec UnixUtils et n'a pas besoin d'installation) exécuté en tant que processus externe. Il prend en charge différentes méthodes de comptage de lignes (comme unix vs mac vs windows).