C # à l'aide de flux

116

Les ruisseaux sont un peu mystérieux pour moi. Je ne sais pas quand utiliser quel flux et comment les utiliser. Quelqu'un peut-il m'expliquer comment les flux sont utilisés?

Si je comprends bien, il existe trois types de flux:

  • stream
  • read stream
  • write stream

Est-ce correct? Et, par exemple, quelle est la différence entre a Memorystreamet a FileStream?

Martijn
la source
13
vous pouvez consulter stackoverflow.com/questions/507747/…
Preets
3
Prenez un tableau d'octets, puis créez un wrapper pour it ( Stream) qui expose certaines méthodes utiles telles que la lecture, l'écriture et le changement de position. Vous pouvez maintenant créer des classes en fonction de leur magasin de stockage (FileStream, MemoryStream) qui héritent de Streamcette fonctionnalité et s'appuient sur celle-ci en fonction du magasin de stockage particulier.
The Muffin Man

Réponses:

80

Un flux est un objet utilisé pour transférer des données. Il existe une classe de flux générique System.IO.Stream, à partir de laquelle toutes les autres classes de flux dans .NET sont dérivées. La Streamclasse traite des octets.

Les classes de flux concrètes sont utilisées pour traiter d'autres types de données que les octets. Par exemple:

  • La FileStreamclasse est utilisée lorsque la source externe est un fichier
  • MemoryStream est utilisé pour stocker des données en mémoire
  • System.Net.Sockets.NetworkStream gère les données du réseau

Les flux de lecture / écriture tels que StreamReaderet StreamWriterne sont pas des flux - ils ne sont pas dérivés System.IO.Stream, ils sont conçus pour aider à écrire et à lire des données depuis et à diffuser!

Arsen Mkrtchyan
la source
3
Donc, si je comprends bien, le flux contient les données et ne fait rien avec. Les classes «d'assistance» de lecture et d'écriture peuvent gérer (manipuler) les données dans le flux?
Martijn
9
Non, Stream n'est pas un conteneur de données, il est utilisé pour transférer des données, par exemple FileStream transfère les données de l'octet [] au fichier phisical, NetworkStream transfère l'octet [] par socket. Les classes Reader Writer sont des classes d'assistance pour écrire et lire à partir d'un flux, par exemple StreamReader peut être utilisé pour lire une chaîne Stream et non l'octet []. si vous donnez FileStream comme paramètre, il lira depuis File, si NetworkStream depuis socket.
Arsen Mkrtchyan
De plus, StreamReader et StreamWriter sont destinés à la lecture et à l'écriture de flux TEXT (caractères).
1c1cle
1
il y a un bon article pour vous aider à comprendre MemoryStream. codeproject.com/Articles/832387/...
Jiaji Li
2
@ user420667. bonne question. Dans les cas AudioStream et TemperatureStream, il s'agit probablement de BinaryStreams pour le pilote associé au périphérique. Vous pouvez également créer un CustomStream spécialement conçu pour l'interface.
1c1cle
62

Pour développer un peu d'autres réponses ici, et aider à expliquer une grande partie de l'exemple de code que vous verrez en pointillés, la plupart du temps, vous ne lisez et n'écrivez pas directement dans un flux. Les flux sont un moyen de bas niveau pour transférer des données.

Vous remarquerez que les fonctions de lecture et d'écriture sont toutes orientées octets, par exemple WriteByte (). Il n'y a pas de fonctions pour traiter les entiers, les chaînes, etc. Cela rend le flux très polyvalent, mais moins simple à utiliser si, par exemple, vous voulez simplement transférer du texte.

Cependant, .NET fournit des classes qui convertissent entre les types natifs et l'interface de flux de bas niveau, et transfère les données vers ou depuis le flux pour vous. Certaines de ces classes notables sont:

StreamWriter // Badly named. Should be TextWriter.
StreamReader // Badly named. Should be TextReader.
BinaryWriter
BinaryReader

Pour les utiliser, vous devez d'abord acquérir votre flux, puis créer l'une des classes ci-dessus et l'associer au flux. Par exemple

MemoryStream memoryStream = new MemoryStream();
StreamWriter myStreamWriter = new StreamWriter(memoryStream);

StreamReader et StreamWriter convertissent entre les types natifs et leurs représentations sous forme de chaîne, puis transfèrent les chaînes vers et depuis le flux sous forme d'octets. Alors

myStreamWriter.Write(123);

écrira «123» (trois caractères «1», «2» puis «3») dans le flux. Si vous avez affaire à des fichiers texte (par exemple html), StreamReader et StreamWriter sont les classes que vous utiliseriez.

Tandis que

myBinaryWriter.Write(123);

écrira quatre octets représentant la valeur entière de 32 bits 123 (0x7B, 0x00, 0x00, 0x00). Si vous avez affaire à des fichiers binaires ou à des protocoles réseau, BinaryReader et BinaryWriter sont ce que vous pouvez utiliser. (Si vous échangez des données avec des réseaux ou d'autres systèmes, vous devez être conscient de l' endianness , mais c'est un autre article.)

Tim Williams
la source
Les classes d'adaptateur StreamWriter et Reader sont sérieusement mal nommées. Merci d'avoir mentionné cela. Comment se fait-il qu'ils aient trouvé ce nom me surprend encore.
Tarik
De plus, même les classes d'écrivain binaire et de lecteur sont mal nommées.
Tarik
22

Les flux sont utiles pour traiter de grandes quantités de données. Lorsqu'il n'est pas pratique de charger toutes les données en mémoire en même temps, vous pouvez l'ouvrir en tant que flux et travailler avec de petits morceaux.

viande
la source
1
J'adorerais voir un exemple de ce que vous venez de dire "travailler avec de petits morceaux".
Jenna Leaf
2
Les flux sont également bons pour de petites quantités de données. Si un programmeur C # veut manipuler le contenu d'un fichier, il / elle doit utiliser des flux, quelle que soit la quantité de données. La même affirmation est vraie pour les flux réseau. Certes, si le programmeur est en train de coder dans un langage de niveau inférieur comme C, il est alors possible d'écrire des caractères ou des octets directement sur un disque ou une socket, mais même pour une petite quantité de données, cela prend du temps et est plus enclin à Erreur.
1c1cle
10

Le flux n'est qu'une abstraction (ou un wrapper) sur un physicalflux d'octets. Ce physicalflux s'appelle le base stream. Il y a donc toujours un flux de base sur lequel un wrapper de flux est créé et donc le wrapper est nommé d'après le type de flux de base FileStream, c'est -à- dire , MemoryStreametc.

L'avantage du wrapper de flux est que vous obtenez une API unifiée pour interagir avec les flux de tout type sous-jacent, usb, fileetc.

Pourquoi traiteriez-vous les données comme un flux - parce que les blocs de données sont chargés à la demande, nous pouvons inspecter / traiter les données sous forme de blocs plutôt que de charger toutes les données en mémoire. C'est ainsi que la plupart des programmes traitent les gros fichiers, par exemple pour crypter un fichier image du système d'exploitation.

Anwar Husain
la source
4

Il n'existe qu'un seul type de base Stream. Cependant, dans diverses circonstances, certains membres lèveront une exception lorsqu'ils seront appelés car dans ce contexte, l'opération n'était pas disponible.

Par exemple, a MemoryStreamest simplement un moyen de déplacer des octets dans et hors d'un morceau de mémoire. Par conséquent, vous pouvez appeler Read and Write dessus.

D'un autre côté, a FileStreamvous permet de lire ou d'écrire (ou les deux) depuis / vers un fichier. Que vous puissiez réellement lire ou écrire dépend de la manière dont le fichier a été ouvert. Vous ne pouvez pas écrire dans un fichier si vous ne l'avez ouvert que pour un accès en lecture.

AnthonyWJones
la source
3

Je commencerais par lire sur les flux sur MSDN: http://msdn.microsoft.com/en-us/library/system.io.stream.aspx

Memorystream et FileStream sont des flux utilisés pour travailler respectivement avec la mémoire brute et les fichiers ...

Robban
la source
Merci pour le lien. J'ai adoré "Vous pouvez parcourir le code source en ligne, télécharger la référence pour une consultation hors ligne et parcourir les sources (y compris les correctifs et les mises à jour) pendant le débogage". Cette fonctionnalité offre un nouveau niveau de perspicacité.
David
1

Je n'appellerais pas ces différents types de flux. La classe Stream a des propriétés CanRead et CanWrite qui vous indiquent si le flux particulier peut être lu et écrit.

La principale différence entre les différentes classes de flux (telles que MemoryStream vs FileStream) est le magasin de sauvegarde - où les données sont lues ou où elles sont écrites. C'est assez évident d'après le nom. Un MemoryStream stocke les données en mémoire uniquement, un FileStream est sauvegardé par un fichier sur disque, un NetworkStream lit les données du réseau et ainsi de suite.

Mattias S
la source