StreamReader.Readline () est-il vraiment la méthode la plus rapide pour compter les lignes dans un fichier?
Tout en regardant autour pendant un moment, j'ai trouvé pas mal de discussions sur la façon de déterminer le nombre de lignes dans un fichier.
Par exemple ces trois:
c# comment puis-je calculer le nombre de lignes dans un fichier texte
Déterminer le nombre de lignes dans un fichier texte
Comment calculer le nombre de lignes rapides?
Donc, je suis allé de l'avant et terminé à l'aide de ce qui semble être la plus efficace (à moins de mémoire?) la méthode que j'ai pu trouver:
private static int countFileLines(string filePath)
{
using (StreamReader r = new StreamReader(filePath))
{
int i = 0;
while (r.ReadLine() != null)
{
i++;
}
return i;
}
}
Mais cela prend une éternité lorsque les lignes elles-mêmes à partir du fichier sont très longues. Est-il vraiment pas une solution plus rapide?
J'ai essayé d'utiliser StreamReader.Read()
ou StreamReader.Peek()
mais je ne peux pas (ou ne savent pas comment) faire l'un ou l'autre de passer à la ligne suivante dès qu'il y a des "trucs" (caractères? texte?).
Des idées s'il vous plaît?
CONCLUSION/RÉSULTATS (Après l'exécution de certains tests sur la base des réponses fournies):
J'ai testé les 5 méthodes ci-dessous sur deux fichiers différents et j'ai obtenu des résultats cohérents qui semblent indiquer que le bon vieux StreamReader.ReadLine()
est encore l'un des moyens les plus rapides... Pour être honnête, je suis perplexe après tous les commentaires et discussion dans les réponses.
Fichier #1:
Taille: 3,631 KO
Lignes: 56,870
Des résultats en quelques secondes pour le Fichier n ° 1:
0.02 --> méthode ReadLine.
0.04 --> méthode de Lecture.
0.29 --> ReadByte méthode.
0.25 --> Readlines.Le comte de la méthode.
0.04 --> ReadWithBufferSize méthode.
Fichier n ° 2:
Taille: 14,499 KO
Lignes: 213,424
Des résultats en quelques secondes pour le Fichier n ° 1:
0.08 --> méthode ReadLine.
0.19 --> méthode de Lecture.
1.15 --> ReadByte méthode.
1.02 --> Readlines.Le comte de la méthode.
0.08 --> ReadWithBufferSize méthode.
Ici sont les 5 méthodes que j'ai testé basé sur tous les commentaires que j'ai reçu:
private static int countWithReadLine(string filePath)
{
using (StreamReader r = new StreamReader(filePath))
{
int i = 0;
while (r.ReadLine() != null)
{
i++;
}
return i;
}
}
private static int countWithRead(string filePath)
{
using (StreamReader _reader = new StreamReader(filePath))
{
int c = 0, count = 0;
while ((c = _reader.Read()) != -1)
{
if (c == 10)
{
count++;
}
}
return count;
}
}
private static int countWithReadByte(string filePath)
{
using (Stream s = new FileStream(filePath, FileMode.Open))
{
int i = 0;
int b;
b = s.ReadByte();
while (b >= 0)
{
if (b == 10)
{
i++;
}
b = s.ReadByte();
}
return i;
}
}
private static int countWithReadLinesCount(string filePath)
{
return File.ReadLines(filePath).Count();
}
private static int countWithReadAndBufferSize(string filePath)
{
int bufferSize = 512;
using (Stream s = new FileStream(filePath, FileMode.Open))
{
int i = 0;
byte[] b = new byte[bufferSize];
int n = 0;
n = s.Read(b, 0, bufferSize);
while (n > 0)
{
i += countByteLines(b, n);
n = s.Read(b, 0, bufferSize);
}
return i;
}
}
private static int countByteLines(byte[] b, int n)
{
int i = 0;
for (int j = 0; j < n; j++)
{
if (b[j] == 10)
{
i++;
}
}
return i;
}
source d'informationauteur sergeidave
Vous devez vous connecter pour publier un commentaire.
Non, il n'est pas. Point est - il matérialise les cordes, ce qui n'est pas nécessaire.
De les COMPTER, vous êtes beaucoup mieux d'ignorer la "chaîne" de la Partie et aller à la "ligne" de la Partie.
une LIGNE est une seriees d'octets se terminant par \r\n (13, 10 - CR LF) ou d'un autre marqueur.
Simplement courir sur les octets, dans un tampon de flux, de compter le nombre d'apparitions de votre marqueur de fin de ligne.
Le meilleur moyen de savoir comment le faire, c'est rapide à réfléchir à la façon la plus rapide de le faire sans l'aide de C/C++.
Dans l'assemblée il y a un CPU au niveau de l'opération, qui scanne la mémoire d'un personnage à l'assemblée vous devez faire ceci
Donc, en C#, vous souhaitez que le compilateur pour obtenir aussi près que possible.
J'ai essayé plusieurs méthodes et testé leurs performances:
Celui qui lit un octet est environ 50% plus lent que les autres méthodes. Les autres méthodes sont tous de retour autour de la même quantité de temps. Vous pouvez essayer de créer des threads et le faire de manière asynchrone, si bien que vous êtes en attente pour une lecture, vous pouvez commencer le traitement d'une précédente lecture. Cela ressemble à un casse-tête pour moi.
Je voudrais aller avec l'un liner:
File.ReadLines(filePath).Count();
il effectue en tant que bien que les autres méthodes que j'ai testé.Oui, la lecture des lignes comme ça, c'est la manière la plus rapide et la plus simple façon dans toute l'acception du terme.
Il n'y a pas de raccourcis ici. Les fichiers ne sont pas de la ligne de base, de sorte que vous devez lire chaque octet du fichier à déterminer le nombre de lignes.
Que TomTom a souligné, la création de chaînes n'est pas strictement nécessaire de compter les lignes, mais une grande majorité du temps passé sera en attente pour la lecture des données à partir du disque. L'écriture d'un beaucoup plus compliqué algorithme serait peut-être raser un pour cent du temps d'exécution, et il permettrait d'améliorer considérablement le temps pour écrire et tester le code.
Il existe de nombreuses façons de lire un fichier. Généralement, le plus rapide moyen est le plus simple:
Cette page fait un excellent comparaison des performances entre plusieurs techniques différentes, y compris à l'aide de BufferedReaders, la lecture en StringBuilder objets, et dans l'ensemble de la matrice.
StreamReader
n'est pas le moyen le plus rapide pour lire les fichiers en général en raison de la faible surcharge de codage des octets de caractères, de sorte que la lecture du fichier dans un tableau d'octets est plus rapide.Les résultats que j'obtiens sont un peu différentes à chaque fois en raison de la mise en cache et d'autres processus, mais ici, c'est l'un des résultats que j'ai obtenu (en millisecondes) avec 16 MO de fichier :
En général
File.ReadLines
devrait être un peu plus lent qu'unStreamReader.ReadLine
boucle.File.ReadAllBytes
est plus lent avec des fichiers plus gros et vont se jeter hors de la mémoire d'exception avec de gros fichiers.La taille par défaut du tampon pour
FileStream
est 4K, mais sur ma machine 64 KO semblait le plus rapide.et testé avec: