web-dev-qa-db-fra.com

ReadAllLines pour un objet Stream?

Il existe un File.ReadAllLines mais pas un Stream.ReadAllLines.

using (Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("Test_Resources.Resources.Accounts.txt"))
using (StreamReader reader = new StreamReader(stream))
{
    // Would prefer string[] result = reader.ReadAllLines();
    string result = reader.ReadToEnd();
}

Existe-t-il un moyen de faire cela ou dois-je parcourir manuellement le fichier ligne par ligne?

53
Ryan Peschel

Vous pouvez écrire une méthode qui lit ligne par ligne, comme ceci:

public IEnumerable<string> ReadLines(Func<Stream> streamProvider,
                                     Encoding encoding)
{
    using (var stream = streamProvider())
    using (var reader = new StreamReader(stream, encoding))
    {
        string line;
        while ((line = reader.ReadLine()) != null)
        {
            yield return line;
        }
    }
}

Puis appelez-le comme:

var lines = ReadLines(() => Assembly.GetExecutingAssembly()
                                    .GetManifestResourceStream(resourceName),
                      Encoding.UTF8)
                .ToList();

La partie Func<> consiste à faire face lors de la lecture plusieurs fois et à éviter de laisser inutilement des flux ouverts. Vous pouvez facilement envelopper ce code dans une méthode, bien sûr.

Si vous n'avez pas besoin de tout cela en même temps, vous n'avez même pas besoin de la variable ToList...

94
Jon Skeet

La propriété .EndOfStream peut être utilisée dans la boucle au lieu de vérifier si la ligne suivante n'est pas nulle.

List<string> lines = new List<string>();

using (StreamReader reader = new StreamReader("example.txt"))
{
    while(!reader.EndOfStream)
    {
        lines.Add(reader.ReadLine());
    }
}
33
Bryan Johnson

L'utilisation de Split ici:

reader
   .ReadToEnd()
   .Split(Environment.NewLine.ToCharArray(), StringSplitOptions.RemoveEmptyEntries);

n'est pas équivalent à ReadLine. Si vous regardez la source de ReadLine, StreamReader.cs , vous verrez qu’elle gère correctement les terminaisons de ligne:\r,\n et\r\n. ReadLine ne renvoie pas de chaîne vide supplémentaire lorsque le terminateur de ligne est\r\n, ce qui est typique sous DOS/Windows. Split "voit" (analyse)\r suivi de\n sous forme de 2 délimiteurs distincts et renvoie une chaîne vide.

'StringSplitOptions.RemoveEmptyEntries' dans le code ci-dessus supprime ces chaînes vides, mais supprime également les lignes vides qui apparaissent également dans l'entrée.

Donc pour l'entrée line1\r \r line3\r ReadLine renvoie 3 lignes. Le 2nd est vide .Split crée 4 chaînes. (Il y a une chaîne supplémentaire après le dernier\r.) Il supprime ensuite les 2e et 4e.

Notez que Split n'est pas bien adapté à l'analyse de lignes de texte délimitées "post-fix". C’est le délimiteur qui apparaît après le jeton. Alors que Split est approprié pour infixe, où les délimiteurs apparaissent entre les jetons. C'est la différence entre a, b, c et line1\r, line2, line3\r. Pour ces entrées, Split renvoie 3 chaînes ou 4 chaînes respectivement.

6
Andrew Dennison
using (Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("Test_Resources.Resources.Accounts.txt"))
using (StreamReader reader = new StreamReader(stream))
{
    // Would prefer string[] result = reader.ReadAllLines();
    string[] result = reader.ReadToEnd().Split(Environment.NewLine.ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
}
6
Steve Danner

En utilisant la méthode d'extension suivante:

public static class Extensions
{
    public static IEnumerable<string> ReadAllLines(this StreamReader reader)
    {
        string line;
        while ((line = reader.ReadLine()) != null)
        {
            yield return line;
        }
    }
}

Il est possible d'obtenir le code souhaité:

using (Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("Test_Resources.Resources.Accounts.txt"))
using (StreamReader reader = new StreamReader(stream))
{
    string[] result = reader.ReadAllLines().ToArray();
}
0
Fidel

Si vous voulez utiliser StreamReader, alors oui, vous devrez utiliser ReadLine et lire en boucle StreamReader, en le lisant ligne par ligne.

Quelque chose comme ca:

string line;

using (StreamReader reader = new StreamReader(stream))
{
    while ((line = reader.ReadLine()) != null)
    {   
        Console.WriteLine(line); 
    }
}

ou essayer

using (StreamReader reader = new StreamReader("file.txt"))
    {

       string[] content = reader.ReadToEnd().Replace("\n","").Split('\t');
    }
0
Coding Duchess