196 votes

Pouvez-vous expliquer le concept de flux ?

Je comprends qu'un flux est une représentation d'une séquence d'octets. Chaque flux permet de lire et d'écrire des octets dans le backing store qui lui est associé. Mais quel est l'intérêt du flux ? Pourquoi n'est-ce pas avec le backing store lui-même que nous interagissons ?

Pour une raison quelconque, ce concept ne me convient pas. J'ai lu un tas d'articles, mais je pense que j'ai besoin d'une analogie ou autre.

245voto

Hosam Aly Points 14797

Le mot "stream" a été choisi parce qu'il représente (dans la vie réelle) une signification très similaire à celle que nous voulons transmettre lorsque nous l'utilisons.

Oublions un peu l'arrière-boutique et pensons à l'analogie avec un cours d'eau. Vous recevez un flux continu de données, tout comme l'eau coule continuellement 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 ; qu'elles proviennent d'un fichier, d'un socket ou de toute autre source, cela n'a (devrait) pas vraiment d'importance. C'est très similaire à la réception d'un jet d'eau, pour lequel vous n'avez pas besoin de savoir d'où il provient ; 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 ne vous souciez que d'obtenir les données dont vous avez besoin, quelle que soit leur provenance, les abstractions dont les autres personnes ont parlé deviennent plus claires. Vous commencez à penser que vous pouvez envelopper les flux, et que vos méthodes continueront à fonctionner parfaitement. Par exemple, vous pourriez 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 modifier 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, puisque vous pouvez utiliser n'importe quel type de source d'entrée, tant que vous pouvez construire un "wrapper" de flux pour elle. Vous pouvez même faire ça :

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());

Vous voyez ? Tant que votre méthode ne se soucie pas de la source d'entrée, vous pouvez personnaliser votre source de diverses 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 ne dispose pas d'un backing store, mais il répond néanmoins parfaitement à nos besoins.

Donc, pour résumer, un flux est juste une source d'entrée, cachant (abstraction) une autre source. Tant que vous ne brisez pas l'abstraction, votre code sera très flexible.

7 votes

La pensée abstraite (et l'explication) semble être dans votre sang ;) Votre analogie avec l'eau (et donc les références métaphoriques) m'a fait penser à Omar Khayyam.

0 votes

@HosamAly Votre explication est très claire mais quelque chose me trouble un peu dans l'exemple de code. La conversion explicite de string en int est faite automatiquement en faisant ReadInt ? Je pense que je pourrais aussi faire ReadString ?

1 votes

@Rushino Il n'y a pas de conversions dans le code ci-dessus. La méthode ReadInt est défini en haut de l'écran par int.Parse qui reçoit la chaîne retournée par reader.ReadLine() et l'analyse. Bien sûr, vous pourriez créer un ReadString méthode. Est-ce assez clair ?

39voto

Jon Skeet Points 692016

Le fait est que vous ne devriez pas avoir à savoir ce qu'est le backing store - c'est une abstraction sur celui-ci. En fait, il pourrait même ne pas y avoir être un magasin de sauvegarde - vous pouvez lire des données à 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 vous adressiez à un système de fichiers, à la mémoire, à un réseau ou à tout autre support de l'idée de flux, votre code est beaucoup plus flexible.

De plus, les flux sont souvent enchaînés - vous pouvez avoir un flux qui compresse tout ce qui est mis dedans, en écrivant la forme comprimée sur un autre flux, ou un flux qui crypte les données, etc. À l'autre extrémité, on trouve la chaîne inverse, qui décrypte, décompresse ou autre.

0 votes

Les différents types de lecteurs de flux utilisés dans l'exemple de @HosamAly ci-dessus n'impliquent-ils pas que vous savez ce qu'est le backing store ? Je suppose que FileStream, NetworkStream etc... lisent à partir de ces types de sources. De plus, existe-t-il des cas où vous ne savez pas quel est le backing store et où il serait choisi dynamiquement pendant l'exécution du programme ? Je n'ai jamais rencontré ce cas et j'aimerais en savoir plus.

0 votes

De même, les flux peuvent-ils acheminer les données par le biais d'un processus au fur et à mesure qu'elles sont générées ou dois-je avoir accès à l'ensemble des données sur lesquelles je veux opérer lorsque je lance le processus ?

0 votes

@user137717 : Non, si vous prenez juste un StreamReader - ou mieux, un TextReader alors votre code ne sait pas quel type de flux sous-tend le flux de données. Ou plutôt, il peut utiliser la fonction BaseStream pour connaître le type - mais il peut s'agir d'un type que votre code n'a jamais vu auparavant. Le fait est que vous ne devriez pas vous en soucier. Et oui, vous pouvez absolument finir par écrire du code qui sera parfois utilisé pour un flux réseau et parfois pour un flux de fichiers. Quant aux flux qui acheminent les données à travers un processus, cela ne se fait pas à l'intérieur de le processus... ce serait le fournisseur de flux.

30voto

Torlack Points 2910

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 besoin de se soucier de savoir si le magasin de sauvegarde est un fichier disque, une mémoire, etc...

0 votes

Oui, cela vous permet d'interchanger le type de flux sans casser votre code. Par exemple, vous pouvez lire un fichier lors d'un appel, puis un tampon mémoire lors du suivant.

0 votes

J'ajouterais que la raison pour laquelle vous voudriez faire cela est que souvent vous n'avez pas besoin de la capacité de recherche de fichier lors de la lecture ou de l'écriture d'un fichier, et donc si vous utilisez un flux, ce même code peut facilement être utilisé pour lire ou écrire dans un socket réseau, par exemple.

12voto

dmajkic Points 2694

Il ne s'agit pas de cours d'eau - il s'agit de natation. Si vous pouvez nager un cours d'eau, alors vous pouvez nager tous les cours d'eau que vous rencontrez.

4voto

vava Points 11364

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, encoder en base64, puis zipper et enfin écrire sur le disque, le tout en une seule ligne !

0 votes

C'est utile, certes, mais je ne dirais pas que c'est le "nerf de la guerre". Même sans chaînage, il est utile d'avoir une abstraction commune.

0 votes

Oui, tu as raison. J'ai changé les mots pour que ce soit plus clair.

0 votes

Oui, c'est mieux. J'espère que vous n'avez pas pensé que j'étais trop pointilleux !

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X