webentwicklung-frage-antwort-db.com.de

ReadAllLines für ein Stream-Objekt?

Es gibt einen File.ReadAllLines, aber keinen 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();
}

Gibt es eine Möglichkeit dafür oder muss ich die Datei manuell zeilenweise durchlaufen?

53
Ryan Peschel

Sie können eine Methode schreiben, die zeilenweise wie folgt liest:

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;
        }
    }
}

Dann nennen Sie es als:

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

Der Func<>-Teil soll beim mehrmaligen Lesen zurechtkommen und vermeiden, dass Streams unnötig geöffnet werden. Sie können diesen Code natürlich leicht in eine Methode einpacken.

Wenn Sie nicht alles auf einmal im Speicher benötigen, brauchen Sie nicht einmal die ToList...

94
Jon Skeet

Die .EndOfStream-Eigenschaft kann in der Schleife verwendet werden, anstatt zu prüfen, ob die nächste Zeile nicht null ist.

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

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

Die Verwendung von Split hier:

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

ist nicht gleichbedeutend mit ReadLine. Wenn Sie sich die Quelle für ReadLine, StreamReader.cs anschauen, werden Sie feststellen, dass Zeilenabschlusszeichen korrekt verarbeitet werden:\r,\n und\r\n. ReadLine gibt keine zusätzliche leere Zeichenfolge zurück, wenn das Zeilenendezeichen\r\n ist. Dies ist typisch für DOS/Windows. Split "sieht" (Parses)\r gefolgt von\n als 2 getrennte Trennzeichen und gibt eine leere Zeichenfolge zurück.

'StringSplitOptions.RemoveEmptyEntries' im obigen Code entfernt diese leeren Zeichenfolgen, entfernt jedoch auch alle leeren Zeilen, die in der Eingabe angezeigt werden.

Also für die Eingabe line1\r \r line3\r ReadLine gibt 3 Zeilen zurück. Die 2. ist leer .Split erstellt 4 Zeichenketten. (Es gibt eine zusätzliche Zeichenfolge nach der letzten\r.) Dann werden die 2. und 4. entfernt.

Beachten Sie, dass Split nicht gut zum Analysieren von Textzeilen geeignet ist, die "nach dem Fixieren" getrennt sind. Das heißt, das Trennzeichen erscheint nach dem Token. Während Split für Infix geeignet ist, werden die Trennzeichen zwischen den Token angezeigt. Es ist die Differenz zwischen a, b, c und line1\r, line2, line3\r. Für diese Eingaben gibt Split 3 oder 4 Zeichenfolgen zurück.

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

Verwenden Sie die folgende Erweiterungsmethode:

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

Es ist möglich, zu Ihrem gewünschten Code zu gelangen:

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

Wenn Sie StreamReader verwenden möchten, dann müssen Sie ReadLine verwenden und den StreamReader durchlaufen und Zeile für Zeile lesen.

Sowas in der Art:

string line;

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

oder Versuche

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

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