Programmation .Net - Indépendance financière

Accéder aux fichiers avec le FileStream en C#/Visual Basic

En programmation C# et Visual Basic, il est vraiment utile de savoir comment accéder aux fichiers. Vous verrez que ce n’est pas si compliqué que ça! Dans l’article suivant, nous verrons comment écrire dans un fichier texte et en faire la lecture par la suite. Nous utiliserons le FileStream, le StreamWriter et le StreamReader parce que ces classes nous donnent plus de contrôle comparativement à la classe File par exemple.

1. Mise en place!

Pour commencer, créez une application de type Console avec Visual Studio (.Net Framework avec Visual Basic ou C#).

Nouvelle application Console avec le .Net Framework.

Petite note en passant pour Visual Basic : Visual Studio créera un module nommé Module1, vous voudrez peut-être renommer ce module pour Program.vb, un peu comme en C# question de garder une certaine constance. Cliquez droit sur le fichier dans le Solution Explorer puis sur Rename, ensuite, cliquez sur Yes quand il vous demandera de renommer aussi les références.

Renommer un fichier en utilisant Visual Basic.

2. Création du FileStream

Pour accéder à un fichier, vous devrez premièrement créer un Stream. Vous pouvez voir ça comme un lien virtuel entre votre programme et le fichier que vous souhaitez accéder. Nous avons deux choix pour exécuter cette action, nous pourrions utiliser la classe File ou encore la classe FileStream.

J’ai choisi la classe FileStream parce que la classe File utilise FileStream en arrière-plan et que cette dernière offre plus de contrôle comme indiqué au début.

C#

using System;
using System.Collections.Generic;
using System.IO;

namespace ConsoleFileAccess
{
    class Program
    {
        static void Main(string[] args)
        {
            string targetFilePath = "text.txt";

            FileStream fileStream = new FileStream(targetFilePath, FileMode.OpenOrCreate, FileAccess.Write, FileShare.None);
        }
    }
}

Note: en C#, le namespace ConsoleFileAccess pourrait être différent pour votre projet dépendamment du nom que vous lui avez donné.

Visual Basic

Imports System.IO
Imports System.Collections.Generic

Module Program

    Sub Main()
        Dim targetFilePath As String = "text.txt"

        Dim fileStream As New FileStream(targetFilePath, FileMode.OpenOrCreate, FileAccess.Write, FileShare.None)
    End Sub

End Module

Dans le code ci-dessus, nous créons le FileStream qui fera le lien avec le fichier text.txt. Here are the different parts of the FileStream constructor that we’re using.

  • Path (variable targetFilePath) est le chemin absolut ou relatif vers votre fichier cible. Un chemin absolut est un chemin exact donc partant de la racine de votre système de fichier. Un chemin relatif se trouve à être depuis l’emplacement actuel de votre exécutable (.exe). Gardez cela en tête sinon vous risquez de ne plus savoir où est votre fichier!
  • FileMode indique ce que vous voulez faire avec le fichier. Dans notre cas nous voulons premièrement écrire dans le fichier donc nous utilisons Write. Plus tard nous voudrons lire alors nous utiliserons Read.
  • FileAccess indiquera au FileStream la façon dont le fichier sera ouvert et accédé. Nous allons commencer par OpenOrCreate qui ouvrira le fichier s’il existe ou le créera si ce n’est pas le cas.
  • FileShare indiquera au système d’opération comment le fichier sera accessible des autres programmes pendant l’accès du nôtre. Par exemple, il est possible de permettre aux autres programmes de lire le fichier durant notre écriture en utilisant Read, mais dans notre cas nous allons utiliser None qui empêche toute action externe, même l’ouverture.

Rappelez-vous qu’il s’agit comme d’un lien virtuel entre notre programme et notre fichier cible et tant que le FileStream est ouvert, le fichier sera accédé et potentiellement bloqué dépendamment du paramètre FileShare. La prochaine étape sera d’écrire dans le fichier avec le StreamWriter!

3. Le StreamWriter

Comme vous pouvez certainement le deviner, le StreamWriter est requis pour écrire “sur” un Stream qui est dans notre cas, le FileStream. En effet, il existe différents types de Stream comme le MemoryStream ou encore le NetworkStream. Ils fonctionnent tous de façon un peu semblable puisqu’ils héritent de la classe Stream.

StreamWriter Constructeur prenant un FileStream en paramètre.

C#

using System;
using System.Collections.Generic;
using System.IO;

namespace ConsoleFileAccess
{
    class Program
    {
        static void Main(string[] args)
        {
            string targetFilePath = "text.txt";

            // StreamWriter
            // Création d'un FileStream et utilisation dans un StreamWriter.
            FileStream writeFileStream = new FileStream(targetFilePath, FileMode.OpenOrCreate, FileAccess.Write, FileShare.None);
            StreamWriter streamWriter = new StreamWriter(writeFileStream);
        }
    }
}

Visual Basic

Imports System.IO
Imports System.Collections.Generic

Module Program

    Sub Main()
        Dim targetFilePath As String = "text.txt"

        ' StreamWriter
        ' Création d'un FileStream et utilisation dans un StreamWriter.
        Dim fileStream As New FileStream(targetFilePath, FileMode.OpenOrCreate, FileAccess.Write, FileShare.None)
        Dim streamWriter As New StreamWriter(fileStream)
    End Sub

End Module

Remarquez que nous passons par paramètre le FileStream directement au constructeur du StreamWriter. C’est de cette façon que ce dernier saura où et comment écrire.

Write et WriteLine

Pour écrire, nous pouvons utiliser Write qui écrira une chaîne de caractères ou encore WriteLine qui écrira aussi une chaîne de caractères mais en y ajoutant un saut de ligne à la fin (\r\n). Pour l’exemple j’utiliserai WriteLine puisque je veux écrire une liste d’étudiants (Students) à un par ligne.

C#

using System;
using System.Collections.Generic;
using System.IO;

namespace ConsoleFileAccess
{
    class Program
    {
        static void Main(string[] args)
        {
            string targetFilePath = "text.txt";

            // StreamWriter
            // Création d'un FileStream et utilisation dans un StreamWriter.
            FileStream writeFileStream = new FileStream(targetFilePath, FileMode.OpenOrCreate, FileAccess.Write, FileShare.None);
            StreamWriter streamWriter = new StreamWriter(writeFileStream);

            // Je crée une liste d'étudiant à écrire dans le fichier.
            List<string> students = new List<string>();

            students.Add("Alex");
            students.Add("John");
            students.Add("Jason");

            // Écriture du nom de chaque étudiant dans le fichier. Attention, il faut appeler Flush ou Close avant que
            // le fichier ne soit réellement modifié, l'écriture est dans la mémoire tampon!
            foreach (string studentName in students)
                streamWriter.WriteLine(studentName);

            // Flush n'est pas obligatoire sauf si vous désirez vider la mémoire tampon dans le fichier. Sinon, Close effectuera cette action pour vous. 
            streamWriter.Flush();
            // Vous n'avez pas à fermer de FileStream, le StreamWriter écrira le contenu restant dans la mémoire et fermera
            // le FileStream pour vous.
            streamWriter.Close();
        }
    }
}

Visual Basic

Imports System.IO
Imports System.Collections.Generic

Module Program

    Sub Main()
        Dim targetFilePath As String = "text.txt"

        ' StreamWriter
        ' Création d'un FileStream et utilisation dans un StreamWriter.
        Dim fileStream As New FileStream(targetFilePath, FileMode.OpenOrCreate, FileAccess.Write, FileShare.None)
        Dim streamWriter As New StreamWriter(fileStream)

        ' Je crée une liste d'étudiant à écrire dans le fichier.
        Dim students As New List(Of String)

        students.Add("Alex")
        students.Add("John")
        students.Add("Jason")

        ' Écriture du nom de chaque étudiant dans le fichier (attention, il faut appeler Flush ou Close avant que
        ' le fichier ne soit réellement modifié, l'écriture est dans la mémoire tampon!
        For Each studentName As String In students
            streamWriter.WriteLine(studentName)
        Next

        ' Flush n'est pas obligatoire sauf si vous désirez vider la mémoire tampon dans le fichier. Sinon, Close effectuera cette action pour vous. 
        streamWriter.Flush()
        ' Vous n'avez pas à fermer de FileStream, le StreamWriter écrira le contenu restant dans la mémoire et fermera
        ' le FileStream pour vous.
        streamWriter.Close()
    End Sub

End Module

La méthode Flush() sert à vider la mémoire tampon dans le fichier donc à envoyer le texte réellement dans le fichier. Autrement dit, quand vous appelez la méthode WriteLine ou Write, le texte n’est pas encore dans le fichier. Ensuite la méthode Close() videra tout le reste de la mémoire tampon dans le fichier puis fermera l’accès donc vous n’avez techniquement pas besoin d’utiliser Flush et Close à moins de vouloir écrire un bout de texte à la fois sans fermer le fichier. J’utilise les deux dans mon exemple pour montrer, mais j’aurais pu simplement mettre Close().

Si vous exécutez le code ci-dessus, vous aurez ce résultat suivant. En passant le fichier se trouvera dans le répertoire de votre projet, vous pouvez cliquer droit sur votre solution dans le Solution Explorer puis -> Open Folder in File Explorer. Ensuite, dirigez-vous vers bin\Debug et vous trouverez text.txt. La raison pour laquelle il se trouve à cet endroit est, comme dit plus haut, dû au fait que nous utilisons un chemin relatif donc il est où se trouve l’exécutable.

Result of the StreamWriter WriteLine Operation.

Intéressant n’est-ce pas! Maintenant à chaque fois que vous exécuterez votre programme il écrira par dessus une partie de l’information dans le fichier. Je dis une partie parce qu’en réalité il commencera à la position 0 puis remplacera chaque caractères l’un après l’autre. Essayez d’exécuter votre code en commentant Jason de la liste d’étudiants. Vous verrez qu’il sera encore là dans le fichier. C’est parce que votre programme aura effacé les deux premiers noms mais pas le dernier, car il ne s’est pas rendu à cette position dans le fichier. Il est possible de changer cette façon de faire en modifiant le FileMode.

C#

//students.Add("Jason");

Visual Basic

'students.Add("Jason")

Create et Append

Comme j’ai mentionné plus haut, changer le FileMode pour Create ou Append modifiera la façon dont on écrira dans le fichier. Create effacera complètement le contenu avant de commencer à écrire alors qu’Append positionnera notre curseur directement à la fin du fichier pour y ajouter de l’information.

Résultat en utilisant le FileMode : Create.

File Mode Create

Résultat en utilisant le FileMode : Append.

File Mode Append.

Vous voyez la différence entre les deux, Create efface complètement le contenu alors qu’Append nous amène à la fin du fichier avant de commencer à écrire. Sentez-vous à l’aise de regarder les autres FileMode et de les essayer. La documentation peut aussi vous aider à comprendre leurs particularités.

4. Le StreamReader

Le StreamReader est vraiment semblable au StreamWriter honnêtement dans sa façon d’être utilisé. Toutefois, le StreamReader sert à lire dans un Stream, plus précisément dans notre cas le FileStream. Voici un exemple.

C#

// StreamReader
// Nous déclarons un autre FileStream pour l'utilisation du StreamReader. Remarquez le changement dans les paramètres
// FileMode et FileAccess.
FileStream readFileStream = new FileStream(targetFilePath, FileMode.OpenOrCreate, FileAccess.Read, FileShare.None);
StreamReader streamReader = new StreamReader(readFileStream);

// Nous pouvons utiliser ReadToEnd qui lira de notre position courante jusqu'à la fin du fichier puis nous
// retourne une chaîne de caractères.
Console.WriteLine("---Lecture avec ReadToEnd---");
string fileContent = streamReader.ReadToEnd();

Console.Write(fileContent);

// Fermeture du StreamReader et, comme avec le StreamWriter, du FileStream associé.
streamReader.Close();
Console.ReadKey();

Visual Basic

' StreamReader
' Nous déclarons un autre FileStream pour l'utilisation du StreamReader. Remarquez le changement dans les paramètres
' FileMode et FileAccess.
Dim readFileStream As New FileStream(targetFilePath, FileMode.OpenOrCreate, FileAccess.Read, FileShare.None)
Dim streamReader As New StreamReader(readFileStream)

' Nous pouvons utiliser ReadToEnd qui lira de notre position courante jusqu'à la fin du fichier puis nous
' retourne une chaîne de caractères.
Console.WriteLine("---Lecture avec ReadToEnd---")
Dim fileContent As String = streamReader.ReadToEnd()

' Fermeture du StreamReader et, comme avec le StreamWriter, du FileStream associé.
streamReader.Close()

' Je montre le contenu dans la Console.
Console.Write(fileContent)
Console.ReadKey()

Même chose, on déclare un FileStream pour créer un lien virtuel entre notre programme et le fichier, puis on l’utilise dans le constructeur par paramètre du StreamReader. Ici j’emploie le FileMode OpenOrCreate pour soit ouvrir ou encore créer le fichier source s’il n’existe pas. Puis pour le FileAccess, j’utilise Read pour spécifier que je ferai la lecture seulement.

Voici le résultat que nous obtenons en ajoutant le code ci-dessus à la suite du code de la section du StreamWriter.

StreamReader read results.

ReadToEnd

En toute franchise, la méthode ReadToEnd() est très probablement celle que vous utiliserez la plus souvent. Elle effectue la lecture de la position courante jusqu’à la fin du fichier et met le résultat dans une variable de type string. Disons que le fichier serait trop volumineux ou que vous voudriez des parties spécifiques, alors vous pourriez utiliser la méthode Read() pour lire un caractère à la fois, ou encore la méthode ReadLine() pour lire ligne par ligne.

Une autre façon de lire le contenu : ReadLine

Comme présenté dans le paragraphe précédant, vous pouvez utiliser ReadLine() pour lire le contenu du fichier une ligne à la fois. Voici un exemple.

C#

// Une autre façon de faire est de lire le texte ligne par ligne en utilisant ReadLine().
// On remet notre position au début du FileStream avec la méthode Seek.
Console.WriteLine("---Lecture ligne par ligne avec ReadLine---");
streamReader.BaseStream.Seek(0, SeekOrigin.Begin);

// Lecture de tout le fichier une fois de plus en écrivant ligne par ligne dans la Console 
// en même temps que de lire dans le fichier.
while (!streamReader.EndOfStream)
    Console.WriteLine(streamReader.ReadLine());

// Fermeture du StreamReader et, comme avec le StreamWriter, du FileStream associé.
streamReader.Close();
Console.ReadKey();

Visual Basic

' Une autre façon de faire est de lire le texte ligne par ligne en utilisant ReadLine().
' On remet notre position au début du FileStream avec la méthode Seek.
Console.WriteLine("---Lecture ligne par ligne avec ReadLine---")
streamReader.BaseStream.Seek(0, SeekOrigin.Begin)

' Lecture de tout le fichier une fois de plus en écrivant ligne par ligne dans la Console 
' en même temps que de lire dans le fichier.
While Not streamReader.EndOfStream
    Console.WriteLine(streamReader.ReadLine())
End While

' Fermeture du StreamReader et, comme avec le StreamWriter, du FileStream associé.
streamReader.Close()
Console.ReadKey()

Remarquez que j’utilise la méthode Seek appelée depuis la propriété BaseStream de l’objet StreamReader. Cette action doit être effectuée parce que nous avons déjà utilisé ReadToEnd et que notre position actuelle dans le fichier est à la fin de ce dernier. Pour revenir au début et recommencer la lecture, nous utilisons Seek.

Code complet

Voici le code complet des fichiers Program.cs (C#) et Program.vb (Visual Basic).

C#

using System;
using System.Collections.Generic;
using System.IO;

namespace ConsoleFileAccess
{
    class Program
    {
        static void Main(string[] args)
        {
            string targetFilePath = "text.txt";

            // StreamWriter
            // Création d'un FileStream et utilisation dans un StreamWriter.
            FileStream writeFileStream = new FileStream(targetFilePath, FileMode.Append, FileAccess.Write, FileShare.None);
            StreamWriter streamWriter = new StreamWriter(writeFileStream);

            // Je crée une liste d'étudiant à écrire dans le fichier.
            List<string> students = new List<string>();

            students.Add("Alex");
            students.Add("John");
            students.Add("Jason");

            // Écriture du nom de chaque étudiant dans le fichier. Attention, il faut appeler Flush ou Close avant que
            // le fichier ne soit réellement modifié, l'écriture est dans la mémoire tampon!
            foreach (string studentName in students)
                streamWriter.WriteLine(studentName);

            // Flush n'est pas obligatoire sauf si vous désirez vider la mémoire tampon dans le fichier. Sinon, Close effectuera cette action pour vous. 
            streamWriter.Flush();
            // Vous n'avez pas à fermer de FileStream, le StreamWriter écrira le contenu restant dans la mémoire et fermera
            // le FileStream pour vous.
            streamWriter.Close();

            // StreamReader
            // Nous déclarons un autre FileStream pour l'utilisation du StreamReader. Remarquez le changement dans les paramètres
            // FileMode et FileAccess.
            FileStream readFileStream = new FileStream(targetFilePath, FileMode.OpenOrCreate, FileAccess.Read, FileShare.None);
            StreamReader streamReader = new StreamReader(readFileStream);

            // Nous pouvons utiliser ReadToEnd qui lira de notre position courante jusqu'à la fin du fichier puis nous
            // retourne une chaîne de caractères.
            Console.WriteLine("---Lecture avec ReadToEnd---");
            string fileContent = streamReader.ReadToEnd();

            Console.Write(fileContent);

            // Une autre façon de faire est de lire le texte ligne par ligne en utilisant ReadLine().
            // On remet notre position au début du FileStream avec la méthode Seek.
            Console.WriteLine("---Lecture ligne par ligne avec ReadLine---");
            streamReader.BaseStream.Seek(0, SeekOrigin.Begin);

            // Lecture de tout le fichier une fois de plus en écrivant ligne par ligne dans la Console 
            // en même temps que de lire dans le fichier.
            while (!streamReader.EndOfStream)
                Console.WriteLine(streamReader.ReadLine());

            // Fermeture du StreamReader et, comme avec le StreamWriter, du FileStream associé.
            streamReader.Close();
            Console.ReadKey();
        }
    }
}

Visual Basic

Imports System.IO
Imports System.Collections.Generic

Module Program

    Sub Main()
        Dim targetFilePath As String = "text.txt"

        ' StreamWriter
        ' Création d'un FileStream et utilisation dans un StreamWriter.
        Dim fileStream As New FileStream(targetFilePath, FileMode.Append, FileAccess.Write, FileShare.None)
        Dim streamWriter As New StreamWriter(fileStream)

        ' Je crée une liste d'étudiant à écrire dans le fichier.
        Dim students As New List(Of String)

        students.Add("Alex")
        students.Add("John")
        students.Add("Jason")

        ' Écriture du nom de chaque étudiant dans le fichier. Attention, il faut appeler Flush ou Close avant que
        ' le fichier ne soit réellement modifié, l'écriture est dans la mémoire tampon!
        For Each studentName As String In students
            streamWriter.WriteLine(studentName)
        Next

        ' Flush n'est pas obligatoire sauf si vous désirez vider la mémoire tampon dans le fichier. Sinon, Close effectuera cette action pour vous. 
        streamWriter.Flush()
        ' Vous n'avez pas à fermer de FileStream, le StreamWriter écrira le contenu restant dans la mémoire et fermera
        ' le FileStream pour vous.
        streamWriter.Close()

        ' StreamReader
        ' Nous déclarons un autre FileStream pour l'utilisation du StreamReader. Remarquez le changement dans les paramètres
        ' FileMode et FileAccess.
        Dim readFileStream As New FileStream(targetFilePath, FileMode.OpenOrCreate, FileAccess.Read, FileShare.None)
        Dim streamReader As New StreamReader(readFileStream)

        ' Nous pouvons utiliser ReadToEnd qui lira de notre position courante jusqu'à la fin du fichier puis nous
        ' retourne une chaîne de caractères.
        Console.WriteLine("---Lecture avec ReadToEnd---")
        Dim fileContent As String = streamReader.ReadToEnd()

        ' Je montre le contenu dans la Console.
        Console.Write(fileContent)

        ' Une autre façon de faire est de lire le texte ligne par ligne en utilisant ReadLine().
        ' On remet notre position au début du FileStream avec la méthode Seek.
        Console.WriteLine("---Lecture ligne par ligne avec ReadLine---")
        streamReader.BaseStream.Seek(0, SeekOrigin.Begin)

        ' Lecture de tout le fichier une fois de plus en écrivant ligne par ligne dans la Console 
        ' en même temps que de lire dans le fichier.
        While Not streamReader.EndOfStream
            Console.WriteLine(streamReader.ReadLine())
        End While

        ' Fermeture du StreamReader et, comme avec le StreamWriter, du FileStream associé.
        streamReader.Close()

        Console.ReadKey()
    End Sub

End Module

En résumer: le FileStream indique où et comment accéder au fichier, le StreamWriter sert à écrire dans le fichier et le StreamReader sert à lire dans le fichier.

Essayez de rouler le code et de mettre des points d’arrêts à différents endroits pour tenter de comprendre mieux le fonctionnement si vous avez de la difficulté. De plus, n’oubliez pas d’appeler la méthode Close() comme il m’arrive souvent de faire!

Vous pourriez utiliser using si vous n’aimez vraiment pas devoir faire un Close manuellement. Le FileStream, StreamReader et StreamWriter implémentent tous l’interface IDisposable ce qui nous permet de remplacer ces actions par le mot clé using. Si vous voulez plus de détails, voici un lien sur le site de Microsoft.

Autres ressources

Si vous désirez plus d’information sur le sujet, vous devriez jeter un coup d’oeil au site de Microsoft sur les entrées et sorties. Je continuerai à ajouter des articles sur le sujet dans le futur, en attendant vous pouvez consulter tous les articles sur la programmation .Net sur cette page. D’autres questions? Alors vous pouvez m’écrire directement en utilisant le formulaire de contact!

Bon code!

Vous avez trouvé un bogue dans mon code? C’est possible, veuillez m’envoyer un message en utilisant mon formulaire de contact pour que je puisse remédier à la situation aussi rapidement que possible!

YouTube

Fichiers du projet

Téléchargez les fichiers ci-dessous pour suivre le live code!

Next article Explication du mode de dépense "juste à temps"
Previous article Utiliser le Join avec LINQ en C#

Related posts

0 Comments

No Comments Yet!

You can be first to comment this post!

Leave a Comment

Your data will be safe! Your e-mail address will not be published. Also other data will not be shared with third person. Required fields marked as *