Ich möchte etwas tun, das ungefähr dem folgenden Codebeispiel entspricht. Ich möchte einen Datenstrom generieren und bereitstellen, ohne dass zu jeder Zeit der gesamte Datensatz im Speicher vorhanden sein muss.
Es scheint, als würde ich eine Implementierung von Stream benötigen, die ein IEnumerable<string>
(oder IEnumerable<byte>
) in ihrem Konstruktor akzeptiert. Intern würde dieser Stream nur den IEnumerable durchlaufen, während der Stream gelesen wird oder wie benötigt. Aber ich kenne keine solche Stream-Implementierung.
Bin ich auf dem richtigen Weg? Weißt du irgendeinen Weg, so etwas zu tun?
%Vor% Ich habe eine Klasse namens ProducerConsumerStream
erstellt, die das tut. Der Produzent schreibt Daten in den Stream und der Kunde liest. Es gibt einen Puffer in der Mitte, so dass der Produzent ein wenig "schreiben" kann. Sie können die Größe des Puffers definieren.
Wie auch immer, wenn es nicht genau ist, was Sie suchen, vermute ich, dass es Ihnen eine gute Vorstellung davon geben wird, wie es gemacht wird. Siehe Erstellen eines neuen Stream-Typs .
Der Link ist veraltet, also habe ich meinen Code hier kopiert. Der ursprüngliche Artikel ist auf dem Wayback-Computer weiterhin verfügbar unter Ссылка
Zuerst die Klasse ProducerConsumerStream
:
Und ein Beispiel, wie man es benutzt:
%Vor%Ich hatte das gleiche Problem. In meinem Fall akzeptiert ein Paket von Drittanbietern nur Streams, aber ich habe ein IEnumerable und konnte keine Antwort online finden, also schrieb ich mein eigenes, das ich teilen werde:
%Vor%In meinem Fall möchte ich es als Eingabe für Datastreams.Csv verwenden:
%Vor%Steve Sadler hat eine perfekt funktionierende Antwort geschrieben. Allerdings macht er es viel schwieriger als nötig
Gemäß der Referenzquelle von TextReader müssen Sie nur Peek und Read überschreiben :
Eine Unterklasse muss die Methoden Peek () und Read () minimal implementieren.
Also schreibe ich zuerst eine Funktion, die IEnumerable<string>
in IEnumerable<char>
konvertiert, wobei am Ende jeder Zeichenkette eine neue Zeile hinzugefügt wird:
Environment.NewLine ist der Teil, der die neue Zeile am Ende jeder Zeichenfolge hinzufügt.
Jetzt ist die Klasse fehlerfrei:
%Vor% Der Konstruktor nimmt eine Sequenz von Zeilen zum Lesen. Es verwendet diese Sequenz und die zuvor geschriebene Funktion, um die Sequenz in eine Folge von Zeichen mit dem hinzugefügten Environment.NewLine
zu konvertieren.
Er ruft den Enumerator der konvertierten Sequenz ab und springt zum ersten Zeichen. Es merkt sich, ob es ein erstes Zeichen in DataAvailable
Jetzt sind wir bereit zu Peek: wenn keine Daten verfügbar sind: gib -1 zurück, ansonsten gib das aktuelle Zeichen als int zurück. Nicht vorwärts gehen:
%Vor%Lesen: Wenn keine Daten verfügbar sind, geben Sie -1 zurück, andernfalls geben Sie das aktuelle Zeichen als int zurück. Gehe zum nächsten Zeichen und achte darauf, ob Daten verfügbar sind:
%Vor%Vergessen Sie nicht, Dispose (bool) zu überschreiben, wo Sie den Enumerator entsorgen.
Das ist alles was benötigt wird. Alle anderen Funktionen verwenden diese beiden.
Nun, um deinen Stream mit den Zeilen zu füllen: IEnumerable Zeilen = ... mit (TextWriter writer = System.IO.File.CreateText (...)) { mit (TextReader reader = new EnumStringReader (Zeilen); { // entweder schreibe pro char: while (reader.Peek ()! = -1) { char c = (char) reader.Read (); writer.Write (c); }
%Vor%Tags und Links asp.net-mvc c# stream