Je comprends qu'un flux est une représentation d'une séquence d'octets. Chaque flux fournit des moyens de lecture et d'écriture d'octets dans sa mémoire de sauvegarde donnée. Mais quel est l'intérêt du flux? Pourquoi le backing store n'est-il pas ce avec quoi nous interagissons?
Pour quelque raison que ce soit, ce concept ne me convient tout simplement pas. J'ai lu un tas d'articles, mais je pense que j'ai besoin d'une analogie ou quelque chose.
Le mot "flux" a été choisi parce qu'il représente (dans la vie réelle) une signification très similaire à ce que nous voulons transmettre lorsque nous l'utilisons.
Oublions un peu le magasin de sauvegarde et commençons à penser à l'analogie avec un jet d'eau. Vous recevez un flux continu de données, tout comme l'eau coule en continu dans une rivière. Vous ne savez pas nécessairement d'où viennent les données, et le plus souvent vous n'en avez pas besoin; que ce soit à partir d'un fichier, d'une socket ou de toute autre source, cela n'a pas (ne devrait pas) vraiment d'importance. Ceci est très similaire à la réception d'un jet d'eau, où vous n'avez pas besoin de savoir d'où il vient; que ce soit d'un lac, d'une fontaine ou de toute autre source, cela n'a pas (ne devrait pas) vraiment d'importance.
Cela dit, une fois que vous commencez à penser que vous vous souciez uniquement d'obtenir les données dont vous avez besoin, peu importe d'où elles viennent, les abstractions dont d'autres personnes ont parlé deviennent plus claires. Vous commencez à penser que vous pouvez encapsuler des flux, et vos méthodes fonctionneront toujours parfaitement. Par exemple, vous pouvez faire ceci:
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);
Comme vous le voyez, il devient très facile de changer votre source d'entrée sans changer votre logique de traitement. Par exemple, pour lire vos données à partir d'un socket réseau au lieu d'un fichier:
Stream stream = new NetworkStream(mySocket);
StreamReader reader = new StreamReader(stream);
int x = ReadInt(reader);
Aussi simple que cela puisse être. Et la beauté continue, car vous pouvez utiliser n'importe quel type de source d'entrée, tant que vous pouvez créer un "wrapper" de flux pour cela. Vous pourriez même faire ceci:
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());
Voir? Tant que votre méthode ne se soucie pas de la source d'entrée, vous pouvez personnaliser votre source de différentes manières. L'abstraction vous permet de découpler l'entrée de la logique de traitement d'une manière très élégante.
Notez que le flux que nous avons créé nous-mêmes n'a pas de magasin de sauvegarde, mais il sert toujours parfaitement nos objectifs.
Donc, pour résumer, un flux n'est qu'une source d'entrée, cachant (abstrait) une autre source. Tant que vous ne rompez pas l'abstraction, votre code sera très flexible.
Le fait est que vous ne devriez pas avoir à savoir ce qu'est le magasin de sauvegarde - c'est une abstraction par-dessus. En effet, il pourrait même ne pas y avoir être un magasin de sauvegarde - vous pourriez lire à partir d'un réseau, et les données ne sont jamais "stockées" du tout.
Si vous pouvez écrire du code qui fonctionne, que vous parliez à un système de fichiers, à la mémoire, à un réseau ou à tout autre élément prenant en charge l'idée de flux, votre code est beaucoup plus flexible.
De plus, les flux sont souvent enchaînés ensemble - vous pouvez avoir un flux qui compresse tout ce qui y est inséré, écrivant le formulaire compressé sur un autre flux, ou un qui crypte les données, etc. À l'autre extrémité, il y aurait l'inverse chaîne, décryptage, décompression ou autre.
Le but du flux est de fournir une couche d'abstraction entre vous et le magasin de sauvegarde. Ainsi, un bloc de code donné qui utilise un flux n'a pas à se soucier si le magasin de sauvegarde est un fichier disque, de la mémoire, etc.
Il ne s'agit pas de ruisseaux - il s'agit de nager. Si vous pouvez nager un ruisseau, vous pouvez nager n'importe quel ruisseau que vous rencontrez.
Pour ajouter à la chambre d'écho, le flux est une abstraction, donc vous ne vous souciez pas du magasin sous-jacent. Cela a plus de sens lorsque vous envisagez des scénarios avec et sans flux.
Les fichiers sont peu intéressants pour la plupart parce que les flux ne font pas beaucoup plus que les méthodes non basées sur les flux que je connais. Commençons par les fichiers Internet.
Si je veux télécharger un fichier depuis Internet, je dois ouvrir un TCP, établir une connexion et recevoir des octets jusqu'à ce qu'il n'y ait plus d'octets. Je dois gérer un tampon, savoir la taille du fichier attendu et écrivez du code pour détecter le moment où la connexion est interrompue et gérer cela de manière appropriée.
Disons que j'ai une sorte d'objet TcpDataStream. Je le crée avec les informations de connexion appropriées, puis je lis les octets du flux jusqu'à ce qu'il dise qu'il n'y a plus d'octets. Le flux gère la gestion du tampon, les conditions de fin de données et la gestion des connexions.
De cette façon, les flux facilitent les E/S. Vous pouvez certainement écrire une classe TcpFileDownloader qui fait ce que fait le flux, mais vous avez alors une classe spécifique à TCP. La plupart des interfaces de flux fournissent simplement une méthode Read () et Write (), et tout concept plus compliqué est géré par l'implémentation interne. Pour cette raison, vous pouvez utiliser le même code de base pour lire ou écrire dans la mémoire, les fichiers disque, les sockets et de nombreux autres magasins de données.
Quand j'ai entendu parler du streaming pour la première fois, c'était dans le contexte du streaming en direct avec une webcam. Ainsi, un hôte diffuse du contenu vidéo et l'autre hôte reçoit le contenu vidéo. Est-ce donc ce streaming? Eh bien ... oui ... mais un flux en direct est un concept concret, et je pense que la question se réfère au concept abstrait de Streaming. Voir https://en.wikipedia.org/wiki/Live_streaming
Alors passons.
La vidéo n'est pas la seule ressource qui peut être diffusée. Le son peut être diffusé. Nous parlons donc maintenant de Streaming Media. Voir https://en.wikipedia.org/wiki/Streaming_media . Comparons maintenant certaines méthodes de livraison de données.
Le téléchargement de fichiers classique ne se fait pas en temps réel. Avant de prendre le fichier à utiliser, vous devrez attendre la fin du téléchargement.
Le téléchargement progressif permet de regarder le fichier vidéo pendant son téléchargement. L'avance et le rembobinage rapides sont possibles. Pour ce faire, il utilise un tampon qui stocke des données temporaires dans la mémoire de l'ordinateur recevant le fichier vidéo. Même si les données sont fragmentées, il ne s'agit pas d'un véritable streaming.
Streaming Se produit en temps réel et fragmente les données. Le streaming est mis en œuvre dans les diffusions en direct. Les clients qui écoutent la diffusion ne peuvent ni avancer ni reculer rapidement. Dans les flux vidéo, les données sont supprimées après la lecture.
Un serveur de streaming conserve une connexion bidirectionnelle avec son client, tandis qu'un serveur Web ferme la connexion après une réponse du serveur.
L'audio et la vidéo ne sont pas la seule chose qui peut être diffusée. Jetons un coup d'œil au concept de flux dans le manuel PHP.
un flux est un objet ressource qui présente un comportement streamable. Autrement dit, il peut être lu à partir de ou écrit dans de façon linéaire mode, et peut être capable de fseek () à un emplacement arbitraire dans le flux.
En PHP, une ressource est une référence à une source externe comme un fichier, une connexion à une base de données. En d'autres termes, un flux est une source qui peut être lue ou écrite. Donc, si vous avez travaillé avec fopen()
, vous avez déjà travaillé avec des flux.
Les fichiers texte, audio et Zip peuvent également être diffusés. En plus de cela, le streaming n'est pas limité aux fichiers. Les connexions HTTP, FTP, SSH et les entrées/sorties peuvent également être diffusées.
Que dit wikipedia sur le concept de streaming?
En informatique, un flux est une séquence d'éléments de données rendus disponibles au fil du temps. Un flux peut être considéré comme des articles sur une bande transporteuse en cours de traitement un à la fois plutôt qu'en gros lots.
Voir: https://en.wikipedia.org/wiki/Stream_%28computing%29 .
Wikipédia renvoie à ceci: https://srfi.schemers.org/srfi-41/srfi-41.html et les auteurs ont ceci à dire sur les flux:
Les flux, parfois appelés listes paresseuses, sont une structure de données séquentielle contenant des éléments calculés uniquement à la demande. Un flux est soit nul, soit une paire avec un flux dans son cdr. Étant donné que les éléments d'un flux sont calculés uniquement lorsqu'ils sont accessibles, les flux peuvent être infinis.
Un Stream est donc en fait une structure de données.
Ma conclusion: un flux est une source qui peut contenir des données pouvant être lues ou écrites de manière séquentielle. Un flux ne lit pas tout ce que la source contient à la fois, il lit/écrit séquentiellement.
Liens utiles:
C'est juste un concept, un autre niveau d'abstraction qui vous facilite la vie. Et ils ont tous une interface commune, ce qui signifie que vous pouvez les combiner à la manière d'un tuyau. Par exemple, encodez en base64, puis Zip puis écrivez ceci sur le disque et le tout sur une seule ligne!
La visualisation que j'utilise est celle des tapis roulants, pas dans les vraies usines parce que je ne sais rien à ce sujet, mais dans les usines de dessins animés où les articles se déplacent le long des lignes et sont estampillés et emballés et comptés et vérifiés par une séquence d'appareils stupides.
Vous avez des composants simples qui font une chose, par exemple un appareil pour mettre une cerise sur un gâteau. Cet appareil possède un flux d'entrée de gâteaux sans cerises et un flux de sortie de gâteaux aux cerises. Il y a trois avantages à mentionner en structurant ainsi votre traitement.
Tout d'abord, cela simplifie les composants eux-mêmes: si vous voulez mettre du glaçage au chocolat sur un gâteau, vous n'avez pas besoin d'un appareil compliqué qui sait tout sur les gâteaux, vous pouvez créer un appareil stupide qui colle du glaçage au chocolat sur tout ce qui y est introduit (dans les dessins animés, cela va jusqu'à ne pas savoir que le prochain article n'est pas un gâteau, c'est Wile E. Coyote).
Deuxièmement, vous pouvez créer différents produits en mettant les appareils en différentes séquences: peut-être que vous voulez que vos gâteaux aient du glaçage sur la cerise au lieu de cerise sur le glaçage, et vous pouvez le faire simplement en échangeant les appareils sur la ligne .
Troisièmement, les appareils n'ont pas besoin de gérer l'inventaire, la boxe ou le déballage. La manière la plus efficace d'agréger et d'emballer les choses est variable: peut-être aujourd'hui vous mettez vos gâteaux dans des boîtes de 48 et les envoyez par camion, mais demain vous voulez envoyer des boîtes de six en réponse aux commandes personnalisées. Ce type de changement peut être pris en compte en remplaçant ou en reconfigurant les machines au début et à la fin de la chaîne de production; la machine cerise au milieu de la ligne ne doit pas être changée pour traiter un nombre différent d'articles à la fois, elle fonctionne toujours avec un article à la fois et elle n'a pas besoin de savoir comment son entrée ou sa sortie est être groupé.
La meilleure explication des flux que j'ai vus est chapitre 3 de SICP . (Vous devrez peut-être lire les 2 premiers chapitres pour que cela ait du sens, mais vous devriez quand même. :-)
Ils n'utilisent pas du tout de stérams pour les octets, mais plutôt des entiers. Les gros points que j'en ai tirés sont:
Un autre point (pour lire la situation du fichier):
stream
peut vous permettre de faire autre chose avant finished reading all content of the file
.Considérez les flux comme une source abstraite de données (octets, caractères, etc.). Ils résument les mécanismes réels de lecture et d'écriture dans la source de données concrète, que ce soit une prise réseau, un fichier sur un disque ou une réponse du serveur Web.
Je pense que vous devez considérer que le magasin de support lui-même n'est souvent qu'une autre abstraction. Un flux de mémoire est assez facile à comprendre, mais un fichier est radicalement différent selon le système de fichiers que vous utilisez, peu importe le disque dur que vous utilisez. En fait, tous les flux ne se trouvent pas au-dessus d'un magasin de sauvegarde: les flux réseau sont à peu près des flux.
Le but d'un flux est que nous limitons notre attention à ce qui est important. En ayant une abstraction standard, nous pouvons effectuer des opérations courantes. Même si vous ne voulez pas, par exemple, rechercher un fichier ou une réponse HTTP pour les URL aujourd'hui, cela ne signifie pas que vous ne le voudrez pas demain.
Les flux ont été conçus à l'origine lorsque la mémoire était minuscule par rapport au stockage. La simple lecture d'un fichier C peut représenter une charge importante. Il était extrêmement important de minimiser l'empreinte mémoire. Par conséquent, une abstraction dans laquelle très peu de choses devaient être chargées était très utile. Aujourd'hui, il est également utile lors de la communication réseau et, il s'avère, rarement aussi restrictif lorsque nous traitons des fichiers. La possibilité d'ajouter de manière transparente des éléments tels que la mise en mémoire tampon d'une manière générale le rend encore plus utile.
Je serai bref, il me manquait juste le mot ici:
Les flux sont files d'attente généralement stockés dans un tampon contenant tout type de données.
(Maintenant, comme nous savons tous ce que sont les files d'attente, il n'est pas nécessaire d'expliquer cela davantage.)
Un flux est un résumé d'une séquence d'octets. L'idée est que vous n'avez pas besoin de savoir d'où viennent les octets, mais que vous pouvez les lire de manière standardisée.
Par exemple, si vous traitez des données via un flux, cela n'a pas d'importance pour votre code si les données proviennent d'un fichier, d'une connexion réseau, d'une chaîne, d'un blob dans une base de données, etc., etc., etc.
Il n'y a rien de mal en soi à interagir avec le magasin de sauvegarde lui-même, sauf pour le fait qu'il vous lie à l'implémentation du magasin de sauvegarde.
Un flux est une abstraction qui fournit un ensemble standard de méthodes et de propriétés pour interagir avec les données. En vous éloignant du support de stockage réel, votre code peut être écrit sans dépendre totalement de ce qu'est ce support ou même de la mise en œuvre de ce support.
Une bonne analogie pourrait être de considérer un sac. Vous ne vous souciez pas de la composition d'un sac ou de ce qu'il fait lorsque vous y mettez vos affaires, tant que le sac remplit la fonction d'être un sac et que vous pouvez récupérer vos affaires. Un flux définit pour les supports de stockage ce que le concept de sac définit pour différentes instances d'un sac (comme un sac poubelle, un sac à main, un sac à dos, etc.) - les règles d'interaction.