Lecture d'un fichier ligne par ligne en C#
Je suis en train de lire des fichiers texte où chaque ligne doit être traité. Pour le moment je suis juste en utilisant un StreamReader, et puis à la lecture de chaque ligne individuellement.
Je me demande si il existe un moyen plus efficace (en termes de LoC et la lisibilité) pour ce faire à l'aide de LINQ sans compromettre l'efficacité opérationnelle. Les exemples que j'ai vu impliquer le chargement de tout le fichier en mémoire, puis de les traiter. Cependant dans ce cas, je ne crois pas que ce serait très efficace. Dans le premier exemple, les fichiers peuvent obtenir jusqu'à environ 50k, et dans le deuxième exemple, toutes les lignes du fichier doit être lu (les tailles sont généralement de < 10k).
On pourrait dire que, de nos jours, il n'a pas vraiment d'importance pour ces petits fichiers, mais je crois que sorte de l'approche conduit à l'inefficacité de code.
Premier exemple:
//Open file
using(var file = System.IO.File.OpenText(_LstFilename))
{
//Read file
while (!file.EndOfStream)
{
String line = file.ReadLine();
//Ignore empty lines
if (line.Length > 0)
{
//Create addon
T addon = new T();
addon.Load(line, _BaseDir);
//Add to collection
collection.Add(addon);
}
}
}
Deuxième exemple:
//Open file
using (var file = System.IO.File.OpenText(datFile))
{
//Compile regexs
Regex nameRegex = new Regex("IDENTIFY (.*)");
while (!file.EndOfStream)
{
String line = file.ReadLine();
//Check name
Match m = nameRegex.Match(line);
if (m.Success)
{
_Name = m.Groups[1].Value;
//Remove me when other values are read
break;
}
}
}
- 50K n'est même pas assez grand pour le faire dans le tas d'objets volumineux. Streaming de sens que si vos fichiers sont dans le mégaoctet (ou plus) de la gamme, pas de kilo-octets.
Vous devez vous connecter pour publier un commentaire.
Vous pouvez écrire un LINQ ligne basée sur le lecteur assez facilement à l'aide d'un itérateur bloc:
ou de faire de Jon heureux:
alors vous avez
ReadFrom(...)
comme un paresseusement évalué séquence sans mise en mémoire tampon, parfait pourWhere
etc.Notez que si vous utilisez
OrderBy
ou de la normeGroupBy
, il va avoir de la mémoire tampon les données dans la mémoire; si vous besoin de regroupement et d'agrégation, "PushLINQ" a peu de fantaisie de code pour vous permettre d'effectuer des agrégations sur les données, mais de les jeter (pas de tampon). Jon explication est ici.static IEnumerable<string> ReadFrom(string file)
, droit?Il est plus simple de lire une ligne et de vérifier si oui ou non nul que pour vérifier EndOfStream tout le temps.
Cependant, j'ai aussi un
LineReader
classe dans MiscUtil qui rend tout cela beaucoup plus simple - fondamentalement, il expose un fichier (ou unFunc<TextReader>
comme unIEnumerable<string>
qui vous permet de faire LINQ des trucs sur elle. Ainsi, vous pouvez faire des choses comme:Le cœur de
LineReader
est-ce la mise en œuvre deIEnumerable<string>.GetEnumerator
:Presque tout le reste de la source est de simplement donner de la souplesse de mise en place
dataSource
(qui est unFunc<TextReader>
).using
déclaration n'est que déjà ladataSource()
appel d'ouvrir le fichier, et donc il va être éliminés à la fin de lausing
déclaration.NOTE: Vous avez besoin de regarder dehors pour le
IEnumerable<T>
solution, car elle entraîne dans le fichier ouvert pour la durée de traitement.Par exemple, avec Marc Gravel réponse:
le fichier restera ouvert pour l'ensemble du traitement.
Merci à tous pour vos réponses! J'ai décidé d'aller avec un mélange, se concentrant principalement sur de Marc, mais, comme j'ai seulement besoin de lire les lignes d'un fichier. Je suppose qu'on pourrait dire de séparation est nécessaire partout, mais hé, la vie est trop courte!
Concernant la tenue du fichier ouvert, qui ne va pas être un problème dans ce cas, le code est une partie d'une application de bureau.
Enfin, j'ai remarqué que vous tous utilisés minuscule string. Je sais en Java il y a une différence entre capitalisés et non capitalisés de la chaîne, mais j'ai pensé en C# minuscule string était juste une référence à capitalisés Chaîne?
Depuis .NET 4.0, le
Fichier.ReadLines()
méthode est disponible.