Pour trouver le moyen le plus rapide de lire un fichier ligne par ligne, vous devrez procéder à une analyse comparative. J'ai fait quelques petits tests sur mon ordinateur mais vous ne pouvez pas vous attendre à ce que mes résultats s'appliquent à votre environnement.
Utilisation de StreamReader.ReadLine
C'est en gros votre méthode. Pour une raison quelconque, vous avez fixé la taille du tampon à la plus petite valeur possible (128). Augmenter cette valeur permet en général d'améliorer les performances. La taille par défaut est de 1 024 et d'autres bons choix sont 512 (la taille du secteur dans Windows) ou 4 096 (la taille du cluster dans NTFS). Vous devrez exécuter un benchmark pour déterminer la taille optimale de la mémoire tampon. Un tampon plus grand est, sinon plus rapide, du moins moins moins lent qu'un tampon plus petit.
const Int32 BufferSize = 128;
using (var fileStream = File.OpenRead(fileName))
using (var streamReader = new StreamReader(fileStream, Encoding.UTF8, true, BufferSize)) {
String line;
while ((line = streamReader.ReadLine()) != null)
// Process line
}
Le site FileStream
vous permet de spécifier Options de fichier . Par exemple, si vous lisez un fichier volumineux de manière séquentielle du début à la fin, vous pouvez bénéficier des avantages suivants FileOptions.SequentialScan
. Encore une fois, l'analyse comparative est la meilleure chose que vous puissiez faire.
Utilisation de File.ReadLines
Cette solution est très proche de la vôtre, sauf qu'elle est mise en œuvre à l'aide d'une StreamReader
avec une taille de tampon fixe de 1 024. Sur mon ordinateur, les performances sont légèrement meilleures que celles de votre code avec une taille de tampon de 128. Cependant, vous pouvez obtenir la même augmentation des performances en utilisant une taille de tampon plus importante. Cette méthode est mise en œuvre en utilisant un bloc d'itérateurs et ne consomme pas de mémoire pour toutes les lignes.
var lines = File.ReadLines(fileName);
foreach (var line in lines)
// Process line
Utilisation de File.ReadAllLines
Cette méthode ressemble beaucoup à la précédente, sauf qu'elle développe une liste de chaînes de caractères utilisée pour créer le tableau de lignes retourné, ce qui nécessite plus de mémoire. Cependant, elle renvoie String[]
et non un IEnumerable<String>
vous permettant d'accéder aux lignes de manière aléatoire.
var lines = File.ReadAllLines(fileName);
for (var i = 0; i < lines.Length; i += 1) {
var line = lines[i];
// Process line
}
Utilisation de String.Split
Cette méthode est considérablement plus lente, du moins pour les gros fichiers (testée sur un fichier de 511 Ko), probablement en raison de la façon dont les fichiers sont traités. String.Split
est mis en œuvre. Il alloue également un tableau pour toutes les lignes, ce qui augmente la mémoire requise par rapport à votre solution.
using (var streamReader = File.OpenText(fileName)) {
var lines = streamReader.ReadToEnd().Split("\r\n".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
foreach (var line in lines)
// Process line
}
Ma suggestion est d'utiliser File.ReadLines
parce qu'il est propre et efficace. Si vous avez besoin d'options de partage spéciales (par exemple vous utilisez FileShare.ReadWrite
), vous pouvez utiliser votre propre code mais vous devez augmenter la taille du tampon.
11 votes
Par
Fastest
vous voulez dire du point de vue de la performance ou du développement ?1 votes
Cela va verrouiller le fichier pour la durée de la méthode. Vous pourriez utiliser File.ReadAllLines dans un tableau, puis traiter ce tableau.
19 votes
BTW, joignez
filestream = new FileStream
enusing()
afin d'éviter d'éventuels problèmes de verrouillage des fichiers.0 votes
En ce qui concerne l'inclusion de FileStream dans l'instruction using(), voir StackOverflow pour la méthode recommandée : StackOverflow utilisation de l'instruction filestream streamreader
0 votes
Je pense que ReadToEnd() est plus rapide.
0 votes
Si vous lisez le flux sous forme de tableaux d'octets, il lira le fichier à partir de 20%~80% plus rapide d'après les tests que j'ai effectués. Ce dont vous avez besoin, c'est de récupérer le tableau d'octets et de le convertir en chaîne de caractères. C'est comme ça que j'ai fait : Pour la lecture, utilisez stream.Read() Vous pouvez faire une boucle pour que la lecture se fasse par morceaux. Après avoir ajouté tout le contenu dans un tableau d'octets (utilisez la fonction System.Buffer.BlockCopy ), vous devrez convertir les octets en chaîne de caractères : Encoding.Default.GetString(byteContent,0,byteContent.Length - 1).Split(new string[] { " \r\n ", " \r ", " \n " }, StringSplitOptions.None) ;