Das Wort "Stream" wurde gewählt, weil es (im wirklichen Leben) eine sehr ähnliche Bedeutung hat wie das, was wir vermitteln wollen, wenn wir es verwenden.
Vergessen wir ein wenig den Hintergrundspeicher und denken über die Analogie zu einem Wasserstrom nach. Sie erhalten einen kontinuierlichen Datenfluss, genau wie Wasser kontinuierlich in einem Fluss fließt. Sie wissen nicht unbedingt, woher die Daten stammen, und müssen dies meistens nicht. Sei es aus einer Datei, einem Socket oder einer anderen Quelle, es spielt keine Rolle (sollte). Dies ist sehr ähnlich wie das Empfangen eines Wasserstroms, wobei Sie nicht wissen müssen, woher es kommt. sei es aus einem See, einem Brunnen oder einer anderen Quelle, es spielt keine Rolle (sollte).
Das heißt, sobald Sie anfangen zu denken, dass Sie sich nur darum kümmern, die Daten zu erhalten, die Sie benötigen, unabhängig davon, woher sie stammen, werden die Abstraktionen, über die andere gesprochen haben, klarer. Sie denken, dass Sie Streams umbrechen können und Ihre Methoden immer noch perfekt funktionieren. Zum Beispiel könnten Sie dies tun:
int ReadInt(StreamReader reader) { return Int32.Parse(reader.ReadLine()); }
// in another method:
Stream fileStream = new FileStream("My Data.dat");
Stream zipStream = new ZipDecompressorStream(fileStream);
Stream decryptedStream = new DecryptionStream(zipStream);
StreamReader reader = new StreamReader(decryptedStream);
int x = ReadInt(reader);
Wie Sie sehen, ist es sehr einfach, Ihre Eingangsquelle zu ändern, ohne Ihre Verarbeitungslogik zu ändern. So lesen Sie beispielsweise Ihre Daten von einem Netzwerk-Socket anstelle einer Datei:
Stream stream = new NetworkStream(mySocket);
StreamReader reader = new StreamReader(stream);
int x = ReadInt(reader);
So einfach wie es nur geht. Und die Schönheit geht weiter, da Sie jede Art von Eingabequelle verwenden können, solange Sie einen Stream- "Wrapper" dafür erstellen können. Sie könnten dies sogar tun:
public class RandomNumbersStreamReader : StreamReader {
private Random random = new Random();
public String ReadLine() { return random.Next().ToString(); }
}
// and to call it:
int x = ReadInt(new RandomNumbersStreamReader());
Sehen? Solange es Ihrer Methode egal ist, um welche Eingabequelle es sich handelt, können Sie Ihre Quelle auf verschiedene Arten anpassen. Mit der Abstraktion können Sie Eingaben auf sehr elegante Weise von der Verarbeitungslogik entkoppeln.
Beachten Sie, dass der Stream, den wir selbst erstellt haben, keinen Hintergrundspeicher hat, aber dennoch perfekt unseren Zwecken dient.
Zusammenfassend ist ein Stream also nur eine Eingabequelle, die eine andere Quelle verbirgt (abstrahiert). Solange Sie die Abstraktion nicht brechen, ist Ihr Code sehr flexibel.
ReadInt
wird ganz oben mit definiertint.Parse
, wobei die zurückgegebene Zeichenfolge empfangenreader.ReadLine()
und analysiert wird. Natürlich können Sie eine ähnlicheReadString
Methode erstellen . Ist das klar genug?Stream.Copy
das Leben in vielen Anwendungen so viel einfacher.Der Punkt ist, dass Sie nicht wissen müssen, was der Hintergrundspeicher ist - es ist eine Abstraktion darüber. Tatsächlich könnte es nicht einmal sein ein Sicherungsspeicher - man von einem Netz liest könnte, und die Daten werden überhaupt nicht „gespeichert“.
Wenn Sie Code schreiben können, der funktioniert, unabhängig davon, ob Sie mit einem Dateisystem, einem Speicher, einem Netzwerk oder etwas anderem sprechen, das die Stream-Idee unterstützt, ist Ihr Code viel flexibler.
Außerdem werden Streams häufig miteinander verkettet - Sie können einen Stream haben, der alles komprimiert, was in ihn eingefügt wird, das komprimierte Formular in einen anderen Stream schreibt oder der die Daten verschlüsselt usw. Am anderen Ende gibt es das Gegenteil Kette, Entschlüsselung, Dekomprimierung oder was auch immer.
quelle
StreamReader
- oder besser ein - nehmen ,TextReader
dann weiß Ihr Code nicht, welche Art von Stream dem Datenfluss zugrunde liegt. Oder besser gesagt, es kann dieBaseStream
Eigenschaft verwenden, um den Typ herauszufinden - aber es kann ein Typ sein, den Ihr Code noch nie zuvor gesehen hat. Der Punkt ist, dass Sie sich nicht darum kümmern sollten. Und ja, Sie können am Ende durchaus Code schreiben, der manchmal für einen Netzwerkstrom und manchmal für einen Dateistream verwendet wird. Was Streams betrifft, die Daten durch einen Prozess leiten - nun, das würde nicht innerhalb des Prozesses geschehen ... es wäre der Stream-Anbieter.Der Zweck des Streams besteht darin, eine Abstraktionsebene zwischen Ihnen und dem Hintergrundspeicher bereitzustellen. Daher muss es einem bestimmten Codeblock, der einen Stream verwendet, egal sein, ob der Sicherungsspeicher eine Festplattendatei, ein Speicher usw. ist.
quelle
Es geht nicht um Bäche - es geht ums Schwimmen. Wenn Sie einen Stream schwimmen können, können Sie jeden Stream schwimmen, dem Sie begegnen.
quelle
Um die Echokammer zu erweitern, ist der Stream eine Abstraktion, sodass Sie sich nicht um den zugrunde liegenden Speicher kümmern. Dies ist am sinnvollsten, wenn Sie Szenarien mit und ohne Streams betrachten.
Dateien sind größtenteils uninteressant, da Streams nicht viel über die mir bekannten nicht-streambasierten Methoden hinaus tun. Beginnen wir mit Internetdateien.
Wenn ich eine Datei aus dem Internet herunterladen möchte, muss ich einen TCP-Socket öffnen, eine Verbindung herstellen und Bytes empfangen, bis keine Bytes mehr vorhanden sind. Ich muss einen Puffer verwalten, die Größe der erwarteten Datei kennen und Code schreiben, um zu erkennen, wann die Verbindung getrennt wird, und dies entsprechend behandeln.
Angenommen, ich habe eine Art TcpDataStream-Objekt. Ich erstelle es mit den entsprechenden Verbindungsinformationen und lese dann Bytes aus dem Stream, bis es heißt, dass keine Bytes mehr vorhanden sind. Der Stream übernimmt die Pufferverwaltung, die Datenendbedingungen und die Verbindungsverwaltung.
Auf diese Weise erleichtern Streams die E / A. Sie könnten sicherlich eine TcpFileDownloader-Klasse schreiben, die das tut, was der Stream tut, aber dann haben Sie eine Klasse, die spezifisch für TCP ist. Die meisten Stream-Schnittstellen bieten lediglich eine Read () - und eine Write () -Methode, und kompliziertere Konzepte werden von der internen Implementierung behandelt. Aus diesem Grund können Sie denselben Basiscode zum Lesen oder Schreiben in Speicher, Festplattendateien, Sockets und viele andere Datenspeicher verwenden.
quelle
Die Visualisierung, die ich verwende, sind Förderbänder, nicht in echten Fabriken, weil ich nichts darüber weiß, sondern in Cartoon-Fabriken, in denen sich Gegenstände entlang von Linien bewegen und von einer Reihe dummer Geräte gestempelt und verpackt und gezählt und überprüft werden.
Sie haben einfache Komponenten, die eines tun, zum Beispiel ein Gerät, mit dem Sie eine Kirsche auf einen Kuchen legen können. Dieses Gerät verfügt über einen Eingangsstrom von kirschlosen Kuchen und einen Ausgangsstrom von Kuchen mit Kirschen. Es gibt drei erwähnenswerte Vorteile, wenn Sie Ihre Verarbeitung auf diese Weise strukturieren.
Erstens vereinfacht es die Komponenten selbst: Wenn Sie Schokoladenglasur auf einen Kuchen legen möchten, benötigen Sie kein kompliziertes Gerät, das alles über Kuchen weiß. Sie können ein dummes Gerät erstellen, das Schokoladenglasur auf alles klebt, was in den Kuchen eingespeist wird (in Bei den Cartoons geht dies so weit, dass man nicht weiß, dass der nächste Gegenstand kein Kuchen ist, sondern Wile E. Coyote.
Zweitens können Sie verschiedene Produkte erstellen, indem Sie die Geräte in verschiedene Sequenzen einordnen: Vielleicht möchten Sie, dass Ihre Kuchen auf der Kirsche statt auf dem Zuckerguss vereist sind, und Sie können dies einfach tun, indem Sie die Geräte auf der Linie vertauschen .
Drittens müssen die Geräte kein Inventar, Boxen oder Unboxing verwalten. Die effizienteste Art, Dinge zu aggregieren und zu verpacken, ist veränderbar: Vielleicht legen Sie Ihre Kuchen heute in Kartons mit 48 Stück und versenden sie per LKW-Ladung, aber morgen möchten Sie Kartons mit sechs Stück als Antwort auf Sonderanfertigungen versenden. Diese Art von Änderung kann durch Ersetzen oder Neukonfigurieren der Maschinen am Anfang und Ende der Produktionslinie berücksichtigt werden. Die Kirschmaschine in der Mitte der Zeile muss nicht geändert werden, um eine andere Anzahl von Elementen gleichzeitig zu verarbeiten. Sie arbeitet immer mit jeweils einem Element und muss nicht wissen, wie die Eingabe oder Ausgabe erfolgt gruppiert werden.
quelle
Als ich zum ersten Mal von Streaming hörte, war es im Zusammenhang mit Live-Streaming mit einer Webcam. Ein Host sendet also Videoinhalte und der andere Host empfängt den Videoinhalt. Also ist das Streaming? Nun ... ja ... aber ein Live-Stream ist ein konkretes Konzept, und ich denke, dass sich die Frage auf das abstrakte Konzept des Streamings bezieht. Siehe https://en.wikipedia.org/wiki/Live_streaming
Also lasst uns weitermachen.
Video ist nicht die einzige Ressource, die gestreamt werden kann. Audio kann auch gestreamt werden. Wir sprechen jetzt über Streaming Media. Siehe https://en.wikipedia.org/wiki/Streaming_media . Audio kann auf vielfältige Weise von der Quelle zum Ziel übertragen werden. Vergleichen wir also einige Datenübermittlungsmethoden miteinander.
Herunterladen klassischer Dateien Das Herunterladen klassischer Dateien erfolgt nicht in Echtzeit. Bevor Sie die Datei verwenden, müssen Sie warten, bis der Download abgeschlossen ist.
Progressiver Download Progressive Download-Chunks laden Daten aus der gestreamten Mediendatei in einen temporären Puffer herunter. Daten in diesem Puffer können verarbeitet werden: Audio-Video-Daten im Puffer können abgespielt werden. Aus diesem Grund können Benutzer die gestreamte Mediendatei beim Herunterladen ansehen / anhören. Ein schneller Vor- und Rücklauf ist möglich, natürlich ohne Puffer. Auf jeden Fall ist progressiver Download kein Live-Streaming.
Streaming Geschieht in Echtzeit und blockiert Daten. Streaming wird in Live-Übertragungen implementiert. Clients, die die Sendung hören, können nicht vor- oder zurückspulen. In Videostreams werden Daten nach der Wiedergabe verworfen.
Ein Streaming-Server unterhält eine bidirektionale Verbindung zu seinem Client, während ein Webserver die Verbindung nach einer Serverantwort schließt.
Audio und Video sind nicht das einzige, was gestreamt werden kann. Schauen wir uns das Konzept der Streams im PHP-Handbuch an.
In PHP ist eine Ressource ein Verweis auf eine externe Quelle wie eine Datei oder eine Datenbankverbindung. Mit anderen Worten, ein Stream ist eine Quelle, aus der gelesen oder geschrieben werden kann. Wenn Sie also mit gearbeitet haben
fopen()
, haben Sie bereits mit Streams gearbeitet.Ein Beispiel für eine Textdatei, die einem Streaming unterzogen wird:
Zip-Dateien können auch gestreamt werden. Darüber hinaus ist das Streaming nicht auf Dateien beschränkt. HTTP-, FTP-, SSH-Verbindungen und Input / Output können ebenfalls gestreamt werden.
Was sagt Wikipedia über das Konzept des Streamings?
Siehe: https://en.wikipedia.org/wiki/Stream_%28computing%29 .
Wikipedia-Links dazu: https://srfi.schemers.org/srfi-41/srfi-41.html und die Autoren haben Folgendes zu Streams zu sagen:
Ein Stream ist also eigentlich eine Datenstruktur.
Mein Fazit: Ein Stream ist eine Quelle, die Daten enthalten kann, aus denen sequentiell gelesen oder geschrieben werden kann. Ein Stream liest nicht alles, was die Quelle enthält, auf einmal, sondern liest / schreibt nacheinander.
Nützliche Links:
quelle
Es ist nur ein Konzept, eine andere Abstraktionsebene, die Ihnen das Leben erleichtert. Und alle haben eine gemeinsame Schnittstelle, was bedeutet, dass Sie sie pfeifenartig kombinieren können. Zum Beispiel in base64 codieren, dann komprimieren und dann auf die Festplatte schreiben und alles in einer Zeile!
quelle
Die beste Erklärung für Streams, die ich gesehen habe, ist Kapitel 3 von SICP . (Möglicherweise müssen Sie die ersten beiden Kapitel lesen, damit es Sinn macht, aber Sie sollten es trotzdem tun. :-)
Sie verwenden überhaupt keine Sterame für Bytes, sondern ganze Zahlen. Die großen Punkte, die ich daraus bekam, waren:
quelle
Ein weiterer Punkt (zum Lesen der Dateisituation):
stream
kann Ihnen erlauben, vorher etwas anderes zu tunfinished reading all content of the file
.quelle
Stellen Sie sich Streams als abstrakte Datenquelle vor (Bytes, Zeichen usw.). Sie abstrahieren die tatsächlichen Mechanismen des Lesens und Schreibens aus der konkreten Datenquelle, sei es ein Netzwerksocket, eine Datei auf einer Festplatte oder eine Antwort vom Webserver.
quelle
Ich denke, Sie müssen berücksichtigen, dass der Hintergrundspeicher selbst oft nur eine andere Abstraktion ist. Ein Speicherstrom ist ziemlich einfach zu verstehen, aber eine Datei unterscheidet sich radikal, je nachdem, welches Dateisystem Sie verwenden, unabhängig davon, welche Festplatte Sie verwenden. Tatsächlich befinden sich nicht alle Streams auf einem Backing Store: Netzwerk-Streams sind so ziemlich nur Streams.
Der Punkt eines Streams ist, dass wir unsere Aufmerksamkeit auf das beschränken, was wichtig ist. Durch eine Standardabstraktion können wir allgemeine Operationen ausführen. Auch wenn Sie beispielsweise heute keine Datei oder HTTP-Antwort nach URLs durchsuchen möchten, heißt das nicht, dass Sie es morgen nicht möchten.
Streams wurden ursprünglich konzipiert, als der Speicher im Vergleich zum Speicher winzig war. Das Lesen einer C-Datei kann eine erhebliche Belastung darstellen. Die Minimierung des Speicherbedarfs war äußerst wichtig. Daher war eine Abstraktion, in die nur sehr wenig geladen werden musste, sehr nützlich. Heutzutage ist es bei der Netzwerkkommunikation gleichermaßen nützlich und, wie sich herausstellt, beim Umgang mit Dateien selten so restriktiv. Die Möglichkeit, Dinge wie das allgemeine Puffern transparent hinzuzufügen, macht es noch nützlicher.
quelle
Ein Stream ist eine Abstraktion einer Folge von Bytes. Die Idee ist, dass Sie nicht wissen müssen, woher die Bytes kommen, sondern dass Sie sie auf standardisierte Weise lesen können.
Wenn Sie beispielsweise Daten über einen Stream verarbeiten, spielt es für Ihren Code keine Rolle, ob die Daten aus einer Datei, einer Netzwerkverbindung, einer Zeichenfolge, einem Blob in einer Datenbank usw. usw. stammen.
An sich ist nichts Falsches an der Interaktion mit dem Backing Store selbst, außer der Tatsache, dass Sie damit an die Implementierung des Backing Stores gebunden sind.
quelle
Ein Stream ist eine Abstraktion, die einen Standardsatz von Methoden und Eigenschaften für die Interaktion mit Daten bereitstellt. Durch Abstrahieren vom eigentlichen Speichermedium kann Ihr Code geschrieben werden, ohne sich vollständig auf das Medium oder die Implementierung dieses Mediums zu verlassen.
Eine gute Analogie könnte darin bestehen, eine Tasche in Betracht zu ziehen. Es ist dir egal, woraus eine Tasche besteht oder was sie tut, wenn du deine Sachen hineinlegst, solange die Tasche die Aufgabe erfüllt, eine Tasche zu sein und du deine Sachen wieder herausholen kannst. Ein Stream definiert für Speichermedien, was das Konzept des Beutels für verschiedene Instanzen eines Beutels (wie Müllsack, Handtasche, Rucksack usw.) definiert - die Regeln der Interaktion.
quelle
Ich werde mich kurz fassen, mir hat hier nur das Wort gefehlt:
Streams sind Warteschlangen, die normalerweise in einem Puffer gespeichert sind, der Daten jeglicher Art enthält.
(Da wir alle wissen, was Warteschlangen sind, müssen wir dies nicht weiter erklären.)
quelle