devstory

Tutoriel C# Stream - flux binaire en C#

  1. Vue d'ensemble sur Stream
  2. Les exemples de base de Stream
  3. FileStream
  4. BufferedStream
  5. MemoryStream
  6. UnmanagedMemoryStream
  7. CryptoStream

1. Vue d'ensemble sur Stream

Stream est une classe qui simule un flux bytes pour être aligné une ligne. Comme la transmission de données sur le réseau, les données transmises sont des flux contigus bytes du premier octet au dernier octet.
Stream est une classe de base, l'autre flux s'étend de cette classe. Quelques classes ont été créées dans C#, qui ont été étendues à partir de la classe Stream pour différentes fins, telles que :
Class
Description
BufferedStream
Un flux utilitaire, il enveloppe (wrap) un autre flux pour améliorer la performance.
FileStream
Le flux est utilisé pour lire les données enregistrées sur le fichier.
MemoryStream
Crée un flux avec les données de la mémoire.
UnmanagedMemoryStream
IsolatedStorageFileStream
PipeStream
NetworkStream
CryptoStream
Lit le flux de données d'écriture qui est crypté
DeflateStream
GZipStream
Stream est une classe abstraite. Elle n'initialise pas un objet par elle -même, vous pouvez donc initialiser un objet Stream à partir des constructeur (Constructor) de la sous classe. La classe Stream fournit des méthodes de fonctionnement de base afin de travailler avec les flux de données, plus précisément ce sont des méthodes de lecture / écriture d'un byte ou d'un ensemble des byte..
Le flux est une classe abstraite, il ne peut pas initialiser un objet par lui-même, vous pouvez initialiser un objet Stream des Constructeurs de la sous-classe. La classe de flux fournit les méthodes de base pour travailler avec les flux de données, à savoir la méthode de lecture / écriture d'un octet ou d'un ensemble d'octets.

 

Selon le flux, il y a le flux qui soutien à la fois la lecture et l'écriture et recherche (seek) en déplaçant le curseur sur le flux, lire et écrire des données en position de curseur.
Les propriétés (property) de Stream :
Attribut
Description
CanRead
Obtient une valeur indiquant si le flux actuel prend en charge la lecture.
CanSeek
Obtient une valeur indiquant si le flux actuel prend en charge la recherche.
CanWrite
Obtient une valeur indiquant si le flux actuel prend en charge l'écriture.
Length
Permet la longueur en octets (bytes) du flux.
Position
Obtient ou définit la position actuelle de ce flux.
Les méthodes de Stream :

2. Les exemples de base de Stream

Avec Stream, vous pouvez écrire chaque byte ou un ensemble des byte dans le flux (stream). Et lorsque vous lisez, vous pouvez lire chaque byte ou plusieurs byte et assigner à un tableau temporaire.
Un byteest de 8 bite, dont un bit est égal à 0 ou 1. Ainsi, 1 byte correspond à un nombre de 0 à 255 (2 ^ 8-1).

L'exemple du flux d'entrée
Et maintenant,nous allons commencer par un exemple simple, créez un Stream qui écrit des données au fichier (File). Vous pouvez écrire chaque octet dans le flux ou écrire un ensemble d'octets dans le flux.
StreamWriteDemo.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;

namespace CSharpStreamsTutorial
{
    class StreamWriteDemo
    {
        public static void Main(string[] args)
        {
            string path = @"C:\temp\MyTest.txt"; 
  
            // Créez le dossier princial.
            Directory.CreateDirectory(@"C:\temp");

            // Créez un objet Stream via Constructor de FileStream.
            // FileMode.Create: Créez un nouveau fichier à enregistrer, si le fichier existe déjà, écraserez ce fichier.
            Stream writingStream = new FileStream(path, FileMode.Create);

            try
            {
                // Un ensemble d'octets. (1 octet <2 ^ 8)
                // Ce tableau correspond à: {'H','e','l','l','o',' ','W','o','r','l','d'}.
                byte[] bytes = new byte[] { 72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100 };

                if (writingStream.CanWrite)
                {
                    writingStream.Write(bytes, 0, bytes.Length); 
                  
                    // Ecrivez un octet (33 = '!')
                    writingStream.WriteByte(33);
                }
            }
            catch (Exception e)
            {
                Console.WriteLine("Error:" + e);
            }
            finally
            {
                // Fermez Stream, libérez des ressources
                writingStream.Close();
            }
            Console.ReadLine();

        }

    }
}
Exécutez l'exemple :
Remarque : Dans le tableau de caractères ASCII, chaque caractère CSII correspond à un nombre <256.
CharacterValueCharacterValue
H72W87
e101r114
l108d100
o11132
!33
Vous pouvez vous faire la référence au tableau des codes ASCII à:
L'exemple de flux d'entrée
L'exemple ci-dessus vous avez écrit des données dans le fichier C:/tempMy/Test.txt, vous pouvez maintenant écrire un flux pour lire les données de ce fichier.
StreamReadDemo.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;

namespace CSharpStreamsTutorial
{
    class StreamReadDemo
    {
        public static void Main(string[] args)
        {
            String path = @"C:\temp\MyTest.txt";

            if (!File.Exists(path))
            {
                Console.WriteLine("File " + path + " does not exists!");
                return;
            }

            // Créez un objet Stream via un constructeur de classe FileStream
            // FileMode.Open: Ouvrez le fichier à lire.
            using (Stream readingStream = new FileStream(path, FileMode.Open))
            {
                byte[] temp = new byte[10];
                UTF8Encoding encoding = new UTF8Encoding(true);

                int len = 0;

                // Lisez des éléments sur Stream et assignez aux éléments du tableau 'temp'.
                // (Assignez au début des positions de 0, chaque fois que la lecture maximale 'temp.Length' élément)
                // En même temps, renvoiez le nombre d'octets vient d'être lu
                while ((len = readingStream.Read(temp, 0, temp.Length)) > 0)
                {
                    // Transformez en chaîne (String).
                    // (des éléments 'len'  commence de la position 0).
                    String s = encoding.GetString(temp, 0, len);
                    Console.WriteLine(s);
                }
            }

            Console.ReadLine();
        }
    }

}
L'exécution l'exemple :

3. FileStream

File Stream est une classe qui s'est étendue de la classe Stream, File Stream est utilisé pour lire et écrire des données au fichier, il hérite des propriétés, des méthodes de Stream et dispose de fonctions supplémentaires pour lire et enregistrer des données sur le fichier.
Ce sont certains modes pour lire et écrire des données :
FileMode
Description
Append
Ouvrit le fichier s'il existe déjà, déplacez le curseur jusqu'à la fin du fichier afin qu'il puisse enregistrer le fichier, si le fichier n'existe pas il sera créé.
Create
Demande le système d'exploitation de créer un nouveau fichier. Si le fichier existe déjà, il sera écrasé.
CreateNew
Demande le système d'exploitation de créer un nouveau fichier. Si le fichier existe déjà IOException sera jeté. Ce mode nécessite le droit FileIOPermissionAccess.Write
Open
Demande le système d'exploitation d'ouvrir un fichier existant. Une exception de System.IO FileNotFoundException est jetée si va...-fichier n’existe pas.
OpenOrCreate
Demande le système d'exploitation d'ouvrir un fichier si elle existe; sinon, un nouveau fichier sera créé.
Truncate
Demande le système d'exploitation d'ouvrir le fichier s'il existe. Et lorsque le fichier est ouvert, il sera coupé le contenu retourné 0 byte.
L'exemple de FileMode:
FileStreamFileModeDemo.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;

namespace CSharpStreamsTutorial
{
    class FileStreamFileModeDemo
    {
        public static void Main(string[] args)
        {
            String path = @"C:\temp\MyTest.txt";

            if (!File.Exists(path))
            {
                Console.WriteLine("File " + path + " does not exists!");

                // Assurez-vous que le répertoire parent existe.
                Directory.CreateDirectory(@"C:\temp");
            }

            // Créez un fichier FileStream pour écrire les données.
            // (FileMode.Append: Ouvrez le fichier pour écrire à la fin du fichier si le fichier ne sort pas, créez-le et écrivez).
            using (FileStream writeFileStream = new FileStream(path, FileMode.Append) )
            {
                string s = "\nHello every body!";

                // Convertissez une chaîne en un tableau d'octets dans le codage UTF8.
                byte[] bytes = Encoding.UTF8.GetBytes(s);

                // ​​​​​​​
                // Écrivez des octets au fichier.
                writeFileStream.Write(bytes, 0, bytes.Length); 
            }
            Console.WriteLine("Finish!");

            Console.ReadLine();
        }
    
    }
}
Exécutez l'exemple :
Avec FileMode.Append, les données seront ajoutées au fichier si le fichier existe déjà :
Constructor:
La classe FileStream possède 11 constructeurs (sans compter des constructeurs obsolètes) utilisés pour initialiser un objet FileStream:
FileStream Constructors
FileStream(SafeFileHandle, FileAccess)     

FileStream(SafeFileHandle, FileAccess, Int32)

FileStream(SafeFileHandle, FileAccess, Int32, Boolean)     

FileStream(String, FileMode)

FileStream(String, FileMode, FileAccess)

FileStream(String, FileMode, FileAccess, FileShare)

FileStream(String, FileMode, FileAccess, FileShare, Int32)

FileStream(String, FileMode, FileAccess, FileShare, Int32, Boolean)

FileStream(String, FileMode, FileAccess, FileShare, Int32, FileOptions)     

FileStream(String, FileMode, FileSystemRights, FileShare, Int32, FileOptions)

FileStream(String, FileMode, FileSystemRights, FileShare, Int32, FileOptions, FileSecurity)
Cependant, vous avez aussi d'autres façons de créer un objet FileStream, comme par le FileInfo, c'est la classe qui représente un fichier dans le système.
Méthode FileInfo renvoie FileStream.
Description
Create()
Par défaut, l'accès complet en lecture / écriture de nouveaux fichiers est accordé à tous les utilisateurs.
Open(FileMode)
Ouvre un fichier à la mode spécifié.
Open(FileMode, FileAccess)
Ouvre un fichier à la mode spécifié avec de la lecture, de l'écriture ou de l'accès en lecture / écriture.
Open(FileMode, FileAccess, FileShare)
Ouvre un fichier à la mode spécifié de la lecture, de l'écriture ou de l'accès en lecture / écriture et l'option de partage spécifiée.
OpenWrite()
Crée un fichier FileStream uniquement en écriture.
OpenRead()
Crée un fichier FileStream uniquement en lecture.
L'exemple de création FileStream via FileInfo:

FileStreamFileInfoDemo.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;

namespace CSharpStreamsTutorial
{
    class FileStreamFileInfoDemo
    {

        public static void Main(string[] args)
        {
            FileInfo afile = new FileInfo(@"C:\temp\MyTest.txt");

            if (afile.Exists)
            {
                Console.WriteLine("File does not exist!");
                Console.Read();
                return;
            }
            // Ouvrez le fichier et tronquez (Truncate) les données actuelles.
            using (FileStream stream = afile.Open(FileMode.Truncate))
            {
                String s = "New text";

                byte[] bytes = Encoding.UTF8.GetBytes(s);

                stream.Write(bytes, 0, bytes.Length);
            }

            Console.WriteLine("Finished!");
            Console.Read();

        }
    }

}

4. BufferedStream

BufferedStream est une classe qui s'est étendue de la classe Stream, c'est un flux (stream) tampon qui enveloppe (wrap) un autre flux et aide à améliorer l'efficacité de la lecture et de l'écriture des données.
BufferedStream a seulement deux méthodes constructeurs (constructor), il enveloppe un autre flux.
Constructeur
Description
BufferedStream(Stream)
Initialise un objet BufferedStream avec la taille de la mémoire tampon par défaut est 4096 octets.
BufferedStream(Stream, Int32)
Initialise un objet BufferedStream avec la taille de la mémoire tampon est spécifié.
Je propose une situation, vous créez un tampon de flux (BufferedStream) couvrant FileStream, dans le but d'écrire des données dans le fichier. Les données écrites dans le tampon du flux seront localisées temporairement en mémoire et, lorsque le tampon est plein, les données sont automatiquement chassées (Flush) au fichier, vous pouvez chasser les données vers le fichier à l'aide de la méthode (Flush) . L'utilisation de BufferedStream dans ce cas réduit le nombre de fois pour écrire le lecteur, ce qui augmente l'efficacité du programme.
L'exemple ci-dessous est un BufferedStream qui enveloppe un flux pour écrire des données dans le fichier :
BufferedStreamWriteFileDemo.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;

namespace CSharpStreamsTutorial
{
    class BufferedStreamWriteFileDemo
    {
        public static void Main(string[] args)
        {
            String fileName = @"C:\temp\MyFile.txt";

            FileInfo file = new FileInfo(fileName);

            // Assurez-vous que le répertoire existe.
            file.Directory.Create();

            // Créez un nouveau fichier, s'il existe, il sera écrasé.
            // Renvoiez un object FileStream.
            using (FileStream fileStream = file.Create())
            {
                // Créez un object BufferedStream enveloppe le FileStream.
                // (Spécifiez un tampon a une capacité de 10000 octets).
                using (BufferedStream bs = new BufferedStream(fileStream, 10000))
                {
                    int index = 0;
                    for (index = 1; index < 2000; index++)
                    {
                        String s = "This is line " + index + "\n";

                        byte[] bytes = Encoding.UTF8.GetBytes(s);

                        // Écrivez dans la mémoire tampon (buffer),
                        // lorsque le tampon est plein, il poussera automatiquement les données dans le fichier.
                        bs.Write(bytes, 0, bytes.Length);
                    }

                    // Stockez les données restantes dans la mémoire tampon dans le fichier.
                    bs.Flush();
                } 
                
            }

            Console.WriteLine("Finished!");
            Console.Read();
        }
    }

}
Les résultats de l'exécution d'exemple:

5. MemoryStream

La classe MemoryStream est directement étendue à partir de la classe Stream, c'est le flux que les données qui sont stockées dans la mémoire.
Essentiellement, MemoryStream est un objet qui gère un tampon (buffer) est un ensemble des byte, tandis que les byte sont écrits dans ce flux seront automatiquement affectés à la position suivante à partir de la position actuelle du curseur sur le tableau. Lorsque le tampon est complet, un nouveau tableau de taille plus grande sera créé et copié les données de l'ancien tableau.
Constructor:
MemoryStream()
MemoryStream(Byte[] buffer)
MemoryStream(Byte[] buffer, Boolean writable)
MemoryStream(Byte[] buffer, Int32 index, Int32 count, Boolean writable)
MemoryStream(Byte[] buffer, Int32 index, Int32 count, Boolean, Boolean publiclyVisible)
MemoryStream(Byte[], Int32, Int32, Boolean, Boolean)
MemoryStream(Int32 capacity)
Exemple:
MemoryStreamDemo.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;

namespace CSharpStreamsTutorial
{
    class MemoryStreamDemo
    {
        static void Main()
        {
            // Créez un objet MemoryStream avec une capacité de 100 octets.
            MemoryStream memoryStream = new MemoryStream(100);

            byte[] javaBytes = Encoding.UTF8.GetBytes("Java");
            byte[] csharpBytes = Encoding.UTF8.GetBytes("CSharp");

            // Écrivez les octets dans memoryStream (flux de mémoire).
            memoryStream.Write(javaBytes, 0, javaBytes.Length);
            memoryStream.Write(csharpBytes, 0, csharpBytes.Length);

            // Écrivez la capacité et la longueur.
            // ==> Capacité: 100, Longueur: 10.
            Console.WriteLine("Capacity: {0} , Length: {1}",
                                  memoryStream.Capacity.ToString(),
                                  memoryStream.Length.ToString());

            // À ce moment, la position du curseur (cursor) est debout après le caractère 'p'.
            // ==> 10.
            Console.WriteLine("Position: "+ memoryStream.Position);

            // Déplacez le curseur vers l'arrière de 6 octets par rapport à la position actuelle.
            memoryStream.Seek(-6, SeekOrigin.Current);

            // Maintenant la position du curseur après le caractère 'a' et avant 'C'.
            // ==> 4.
            Console.WriteLine("Position: " + memoryStream.Position);

            byte[] vsBytes = Encoding.UTF8.GetBytes(" vs ");

            // Écrivez des données dans le memoryStream (flux de mémoire).
            memoryStream.Write(vsBytes, 0, vsBytes.Length);


            byte[] allBytes = memoryStream.GetBuffer();

            string data = Encoding.UTF8.GetString(allBytes);

            // ==> Java vs rp
            Console.WriteLine(data);

            Console.WriteLine("Finish!");
            Console.Read();

             
        }
    }

}
Exécutez l'exemple :

6. UnmanagedMemoryStream

L'utilisation UnmanagedMemoryStream vous permet de lire le flux de données qui n'est pas géré sans les copier pour gérer la mémoire Heap avant de l'utiliser. Cela vous permet d'économiser de la mémoire si vous devez gérer de nombreuses données.
Notez qu'il y a une limite de 2GB pour MemoryStream, donc vous devez utiliser UnmanagedMemoryStream si vous dépassez cette limite.
J'ai proposé une situation: il existe des données discrètes disponibles sur la mémoire. Et vous pouvez les rassembler pour gérer par UnmanagedMemoryStream en contrôlant les pointeurs des données discrètes précitées, au lieu de les copier dans le flux à gérer.
Constructor:
UnmanagedMemoryStream()
UnmanagedMemoryStream(Byte* pointer, Int64 length)
UnmanagedMemoryStream(Byte* pointer, Int64 length, Int64 capacity, FileAccess access)
UnmanagedMemoryStream(SafeBuffer buffer, Int64 offset, Int64 length)
UnmanagedMemoryStream(SafeBuffer buffer, Int64 offset, Int64 length, FileAccess access)
  • TODO

7. CryptoStream

CryptoStream est une classe utilisée pour chiffrer des flux de données.
L'image ci-dessous illustre que CryptoStream emballe un autre flux (tel que l'écriture d'un fichier de flux), lorsque vous écrivez des données d'octet sur CryptoStream, ces octets seront chiffrés dans un autre octet avant de débiter le flux qui est écrit dans le fichier. Maintenant, le contenu du fichier a été chiffré.

Notez que vous pouvez choisir un algorithme de cryptage lors de la création de l'objet CryptoStream.

Dans une situation inverse, CryptoStream emballe un fichier de flux de lecture (le fichier dont le contenu a été crypté ci-dessus), l'octet dans FileStream a été crypté, il sera déchiffré par CryptoStream.
Une autre chose importante dont vous devez vous rappeler est que tout algorithme de chiffrement n'a pas deux manières de cryptage et des solutions de décryptage.
Voyez un exemple :

Ici, j'utilise l'algorithme DES pour crypter et décrypter, vous devez fournir le tableau de 128 bits qui est la clé de votre sécurité.

DES Algorithm
// Des objects fournissent l'algorithme de cryptage DES.
DESCryptoServiceProvider provider = new DESCryptoServiceProvider();

// Utilisez votre clé privée (private key) (doit être une chaîne 128bit = 8byte).
// (Équivalent à 8 caractères ASCII)
provider.Key = ASCIIEncoding.ASCII.GetBytes("1234abcd");
provider.IV = ASCIIEncoding.ASCII.GetBytes("12345678");

// Crypteur (Encryptor).
ICryptoTransform encryptor = provider.CreateEncryptor();

// Decrypteur (Decrytor).
ICryptoTransform decryptor = provider.CreateDecryptor();
Voyez l'exemple complet.
CryptoStreamExample.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.Security.Cryptography;

namespace CSharpStreamsTutorial
{
    class CryptoStreamExample
    {
        public static void Main(string[] args) 
        {
            // Fournit l’algorithme de cryptage DES.
            DESCryptoServiceProvider provider = new DESCryptoServiceProvider();

            // Clé de sécurité (secret key) (doit être une chaîne de 128 bits = 8 bytes).
            // (Équivalent à 8 caractères ASCII)
            provider.Key = ASCIIEncoding.ASCII.GetBytes("1234abcd");
            provider.IV = ASCIIEncoding.ASCII.GetBytes("12345678");


            String encryedFile = @"C:\temp\EncryptedFile.txt";

            // Un flux pour écrire un fichier.
            using (FileStream stream = new FileStream(encryedFile, FileMode.OpenOrCreate, FileAccess.Write))
            { 
                // Cryptage des sujets (Encryptor).
                ICryptoTransform encryptor = provider.CreateEncryptor();

                // Créer CryptoStream enveloppe le FileStream.
                // (FileStream dans ce cas utilisé pour écrire des données dans le fichier)
                using (CryptoStream cryptoStream = new CryptoStream(stream,
                                     encryptor, CryptoStreamMode.Write))
                {
                    // Un tableau d'octets n'est pas cryptées.
                    byte[] data = ASCIIEncoding.ASCII.GetBytes("Bear, I love you. OK?");

                    // Écrire à cryptoStream.
                    cryptoStream.Write(data, 0, data.Length);
                } 

            }
            Console.WriteLine("Write to file: " + encryedFile);

            // Ensuite, lisez le fichier qui a été chiffré et vient de créer dans les étapes ci-dessus.
            using (FileStream stream = new FileStream(encryedFile, FileMode.Open, FileAccess.Read))
            {
                // Décrypteur (Decryptor).
                ICryptoTransform decryptor = provider.CreateDecryptor();

                // Créez CryptoStream qui enveloppe FileStream.
                // (FileStream dans ce cas pour utiliser écrire le fichier).
                using (CryptoStream cryptoStream = new CryptoStream(stream,
                                     decryptor, CryptoStreamMode.Read))
                {
                    byte[] temp = new byte[1024];
                    int read=0;
                    while((read =cryptoStream.Read(temp,0,temp.Length )) >0 )
                    {
                        String s= Encoding.UTF8.GetString(temp,0,read);

                        Console.Write(s);
                    } 
                } 
            }

            // Finished
            Console.Read();
        }
    }

}
Exécutez l'exemple :
Observez le contenu du fichier qui vient de créer.