Site:  Cours VB.net  
4.6 Les fichiers.

          

Comment lire et écrire dans des fichiers du texte, des octets, du XML du Rtf ?

Les Classes du Framework

FileOpen

Les objets

Les nouveautés de VS 2005

Comment ouvrir une boite de dialogue pour choisir un fichier? 

Un exemple de classe permettant d'enregistrer une variable structurée avec des FileStream.

Généralités et rappels:

Le mot  'fichier'  est a prendre au sens informatique: ce n'est pas un ensemble de fiches mais plutôt un ensemble d'octets. Un fichier peut être un programme (Extension .EXE), du texte (Extension .TXT ou .DOC....), une image (Extension .BMP .GIF .JPG...), une base de données (.MDB..) du son, de la vidéo....

Pour travailler avec du texte, des octets, des données très simple (sans nécessité d'index, de classement..), on utilise les méthodes décrites dans cette page: travail direct dans les fichiers séquentiels, aléatoires, binaires. Mais dès que les informations sont plus structurées, il faut utiliser les bases de données (Il y a plusieurs chapitre plus loin traitant des bases de données).

Un fichier a un nom: 'Image.GIF' , une extension: '.GIF' qui en indique généralement le type de contenu , des attributs (Longueur, Date de création, de modification, Fichier en lecture seule ou non..).

On voit cela dans l'explorer Windows:

 

Un fichier est composé d'enregistrements qui sont des 'paquets' de données; suivant le type de fichier un enregistrement peut correspondre à une ligne, un octet, un groupe d'octets..

Un fichier peut être vu comme contenant du texte, de l'XML, des octets.

Comment utiliser les fichiers? Voici le plan de cet article:

A- Il est conseillé de travailler avec les Classes du Frameworks

Avec la Classe FileInfo, on obtient des renseignements sur le fichier.

Pour lire écrire dans un fichier (en dehors des bases de données), il y a plusieurs méthodes:

 Avec la Classe System.Io on a a notre disposition StreamReader StreamWriter BinaryReader BinaryWriter FileStream:

Pour lire ou écrire dans un fichier, il faut l'ouvrir (Open), lire ou écrire en utilisant un flux de données (Stream) puis le refermer (Close).

Le Stream (flux, torrent, courant) est une notion générale, c'est donc un flux de données provenant ou allant vers un fichier, un port, une connexion TCP/IP...

L'accès est séquentiel: les données sont traitées  du début à la fin du fichier.

 

B- Il existe toujours la méthode classique du FileOpen:

On ouvre le fichier en mode séquentiel, aléatoire, binaire, on lit X enregistrements, on referme le fichier.

 

C- Avec certains objets, on gèrent automatiquement les lectures écritures sur disque.

Comme avec le RichTextBox par exemple.

 

En résumé, pour travailler sur les fichiers, on dispose:

 

Les 2 derniers font appel au premier; donc pourquoi ne pas utiliser directement les Classe .NET?

 

A- Classe  FileInfo et File, Stream.

Pour travailler sur les fichiers, il faut au préalable taper:

Imports System.IO

La classe File est utilisée pour travailler sur un ensemble de fichier ou un fichier (sans instanciation préalable: ce sont des méthodes statiques), la Classe FileInfo donne des renseignements sur un fichier particulier (Il faut instancier au préalable un objet FileInfo).

La Classe File possède les méthodes suivantes.

Exists            Teste si le fichier existe.

Create            Crée le fichier

Copy              Copie le fichier

Delete            Efface le fichier

GetAttributes , SetAttributes     Lire ou écrire les attributs.

GetCreationTime , GetLastAccessTime , GetLastWriteTime et les Set.. correspondant.

Move              Déplacement de fichier

Replace           Framework 2

ReadAllText, WriteAllText   Framework 2 lire ou écrire un texte dans un fichier

ReadAllLines, WriteAllLines   Framework 2 lire ou écrire des lignes dans un fichier

ReadAllBytes, WriteAllBytes   Framework 2 lire ou écrire des octets dans un fichier

Toutes les méthodes Open (pour un FileStream) OpenRead, OpenWrite, OpenText.

Exemple:

Un fichier existe-t-il? Afficher True s'il existe:

Label1.Text = File.Exists("vessaggi.gif").ToString

Exists est bien une 'méthode de Classe': pas besoin d'instancier quoi que ce soit.

 

Déplacer un fichier de c: vers d:?

File.Move("c:\monText.txt", "d:\monText.txt")

Copier un fichier de c: vers d:?

File.Copy("c:\monText.txt", "d:\monText.txt", True)

Le dernier argument facultatif (framework 2) permet de remplacer cible s'il existe.

Sauvegarde un fichier et le remplace? (Framework 2)

File.Copy("c:\monText.txt", "c:\newText.txt",, "c:\newText.bak " True)

Sauvegarde monText.tx sans un .bak , puis  copie NewText.txt dans monText.tx ; True permet de remplacer cible s'il existe.

Efface un fichier:

File.Delete("d:\monText.txt")

Lire la totalité d'un fichier texte? (Framework 2)

Dim myText As String =File.ReadAllText("c:\monText.txt")

File.WriteAllText("c:\monText.txt", myText) 'pour réecrire le texte dans un autre fichier.

La méthode AppendAllText existe aussi.

Lire et mettre dans un tableau les lignes d'un fichier texte? (Framework 2)

Dim myLines() As String =File.ReadAllLines("c:\monText.txt")

Lire et mettre dans un tableau les octets d'un fichier? (Framework 2)

Dim myBytes() As Byte =File.ReadAllBytes("c:\monText.txt")

Un fichier est-il en lecture seule?

If File.GetAttributes("c:\monText.txt") And FileAttributes.ReadOnly Then..

 

La Classe FileInfo possède les propriétés suivantes.

Name            Nom du fichier (sans chemin)

FullName        Nom complet avec chemin

Extension       Extension   (.txt par exemple)

Length          Longueur du  fichier.

Directory       Répertoire parent

DirectoryName   Répertoire ou se trouve le fichier

Exists          Existe?

LastAccessTime  Date du dernier accès, LastWriteTime existe aussi.

Attributes      Attributs

Il faut faire un AND entre Attributes et une valeur de l'énumération FileAttributes ( Archive, Compressed, Directory, Encrypted, Hidden, Normal, ReadOnly, System, Temporaly).

Pour tester ReadOnly par exemple:

Dim sNom As String = "c:\monfichier.txt"

Dim Fi As FileInfo      'On déclare un FileInfo

Fi=New FileInfo( sNom)  'On instancie ce FileInfo avec comme paramètre le nom du fichier

 

Fi.Attributes And FileAttributes.ReadOnly    Retourne True si le fichier est ReadOnly

 

Et aussi:

Fi.Name retourne "monfichier.txt"

Fi.FullName retourne "c:\monfichier.txt"

Fi.Name.Substring(0, Fi.Name.LastIndexOf(".")) retourne "monfichier" : pas de chemin ni d'extension.

 

 

Et les méthodes suivantes:

Create, Delete, MoveTo

AppendTex, CopyTo Open, OpenRead, OpenWrite, OpenText..

On voit que toutes les informations sont accessibles.

 

Exemple:

Pour un fichier, afficher successivement le nom, le nom avec répertoire, le répertoire, la longueur, la date de dernière écriture et si le fichier est en ReadOnly.

Dim sNom As String = "c:\monfichier.txt"

Dim Fi As FileInfo  'On déclare un FileInfo

Fi=New FileInfo( sNom)  'on instance ce FileInfo avec comme paramètre le nom du fichier

    MsgBox("Nom="& Fi.Name)

    MsgBox("Nom complet ="& Fi.FullName)

    MsgBox("Répertoire="& Fi.DirectoryName)

    MsgBox("Longueur="& Fi.Length.ToString)

    MsgBox("Date der modification="& Fi.LastWriteTime.ToShortDateString)

    MsgBox("ReadOnly="& (Fi.Attributes And FileAttributes.ReadOnly).ToString)

 

Classe My.Computer.FileSystem en VS 2005.

En VS 2005 il y a en plus la classe My.Computer.FileSystem qui simplifie énormément les choses:

les méthodes CopyFile, DeleteFile, FileExits permettent de copier, effacer un fichier ou de voir s'il existe. Il existe aussi RenameFile et MoveFile.

Exemple :

Afficher dans une MsgBox True si 'c:\config.sys' existe.

MsgBox(My.Computer.FileSystem.FileExists("c:\config.sys").ToString)

Exemple :

Afficher la liste des fichiers qui sont sous c:\; ici on utilise GetFiles qui retourne une collection des fichiers.(count contient le nombre de  fichiers, item () les noms.

Dim i As Integer

For i = 0 To My.Computer.FileSystem.Getfiles("c:\").Count - 1

ListBox1.Items.Add(My.Computer.FileSystem.GetFiles("c:\").Item(i))

Next i

Un fichier existe t-il et est-il ouvert et utilisé par une autre application?

If My.Computer.FileSystem.FileExists("c:\monText.txt") Then

Try

   'on tente d'ouvrir un stream sur le fichier, s'il est déjà utilisé, cela déclenche une erreur.

   Dim fs As IO.FileStream = My.Computer.FileSystem.GetFileInfo("c:\monText.txt").Open(IO.FileMode.Open, IO.FileAccess.Read)

   fs.Close()

Catch ex As Exception

  MsgBox("Le fichier  est déjà ouvert")

End Try

End If

 

 

 

Utiliser les "Stream".

 

Le Stream (flux, torrent, courant) est une notion générale, c'est donc un flux de données provenant ou allant vers un fichier, un port, une connexion TCP/IP...

Ici on utilise un Stream pour lire ou écrire dans un fichier.

L'accès est séquentiel: les données sont traitées du début à la fin du fichier.

Pour écrire dans un fichier texte:

Il  faut instancer un objet de la classe StreamWriter . On écrit avec Write ou WriteLine.(ajoute un saut de ligne)  Enfin on ferme avec Close.

On peut instancier avec le constructeur de la classe StreamWriter et avec New, ou par la Classe File.

Dim SW As New StreamWriter ("MonFichier.txt") ' crée ou si existe écrase

 

Il existe une surcharge permettant de ne pas écraser mais d'ajouter à la fin du fichier:

Dim SW As New StreamWriter ("MonFichier.txt", True) ' crée ou si existe ajoute

 

Avec la classe File:

Dim SW As  StreamWriter=File.CreateText ("MonFichier.txt") ' crée ou si existe écrase

Dim SW As StreamWriter = File.AppendText("MonFichier.txt") ' crée ou si existe ajoute

 

Ensuite pour écrire 2 lignes:

SW.WriteLine ("Bonjour")

SW.WriteLine ("Monsieur")

 

Enfin on ferme:

SW.Close()

 

Pour lire dans un fichier Texte:

Il faut instancier un objet de la classe StreamReader. On lit avec Read (un nombre d'octet) ReadLine (une ligne) ReadToEnd (de la position courante jusqu'à la fin). Enfin on ferme avec Close.

Avec le constructeur de la Classe Stream Reader:

Dim SR As New StreamReader ("MonFichier.txt")

Avec la Classe File:

Dim SR As  StreamReader=File.OpenText ("MonFichier.txt") '

 

Comment lire chaque ligne du fichier et s'arrêter à la fin?

En effet on ne sait pas habituellement combien le fichier contient de ligne, si le fichier contient 2 lignes il faut en lire 2 et s'arrêter sinon on tente de lire après la fin du fichier et cela déclenche une erreur.

3 solutions:

1-Utiliser ReadToEnd qui lit en bloc jusqu'à la fin.

2-Avant ReadLine mettre un Try: quand l'erreur 'fin de fichier' survient elle est interceptée par Catch qui sort  du cycle de lecture et ferme le fichier.

3-Utiliser Peek qui lit dans le fichier un caractère mais sans modifier la position courante de lecture.

La particularité de Peek est de retourner -1 s'il n'y a plus de caractère à lire sans déclencher d'erreur, d'exception.

La troisième solution est la plus générale et la plus élégante:

Do Until SR.Peek=-1

     Ligne=SR.ReadLine()

Loop

Enfin on ferme:

SR.Close()

 

Notion de 'Buffer', utilisation de Flush.

En fait quand on écrit des informations sur le disque, le logiciel travaille sur un buffer ou mémoire tampon qui est en mémoire vive. Si on écrit des lignes dans le fichier, elles sont 'écrites' dans le buffer en mémoire vive. Quand le buffer est plein,(ou que l'on ferme le fichier) l'enregistrement du contenu du buffer est effectué effectivement sur le disque.

Ce procédé est général à l'écriture et à la lecture de fichier mais totalement transparent car le programmeur ne se préoccupe pas des buffers.

Parfois, par contre, même si  on a enregistré peu d'information, on veut être sûr qu'elle est sur le disque, il faut donc forcer l'enregistrement sur disque même si le buffer n'est pas plein, on utilise alors la méthode Flush.

  SW.Flush()

Le fait de fermer un fichier par Close, appelle automatiquement Flush() ce qui enregistre des données du buffer.

 

B- Utiliser "FileOpen".

Visual Basic fournit trois types d'accès au fichier :

Philippe
Jean-François
Louis

On ne peut qu'écrire le premier enregistrement puis le second, le troisième, le quatrième...

Pour lire c'est pareil: on ouvre , on lit le premier, le second, le troisième, le quatrième....

Pour lire le troisième enregistrement , il faut lire  avant les 2 premiers.

Philippe

1 place de la gare

Jean

35 rue du cloître

Pierre

14 impasse du musée

Louis

sdf

 

Les enregistrements ont une longueur fixe: il faut prévoir!! si on décide de 20 caractères pour le prénom, on ne pourra pas en mettre 21, le 21ème sera tronqué, à l'inverse l'enregistrement de 15 caractères sera complété par des blancs.

Il n'y a pas de séparateur entre les enregistrements.

Les enregistrements peuvent être constitués d'un ensemble de variables: une structure, ici prénom et adresse.

Ensuite on peut lire directement n'importe quel enregistrement,le second enregistrement par exemple, ou écrire sur le 3éme.(on comprend que, connaissant la longueur d'un enregistrement qui est fixe, l'ordinateur peut calculer la position d'un enregistrement quelconque.)

 

 

En pratique:

Les fichiers séquentiels sont bien pratique pour charger une série de ligne, (toujours la même)  dans une ListBox par exemple.

Faut-il utiliser les fichiers séquentiels ou random (à accès aléatoire, à accès direct) pour créer par exemple un petit carnet d'adresse?

Il y a 2 manières de faire:

Bien sur s'il y a de nombreux éléments dans une adresse, un grand nombre d'adresse, il faut utiliser une base de données.

 

Si on ouvre un fichier en écriture et qu'il n'existe pas sur le disque, il est crée.

Si on ouvre un fichier en lecture et qu'il n'existe pas, une exception est déclenchée (une erreur). On utilisait cela pour voir si un fichier existait: on l'ouvrait, s'il n'y avait pas d'erreur c'est qu'il existait. Mais maintenant il y a plus simple pour voir si un fichier existe (File.Exists).

Si on ouvre un fichier et que celui-ci est déjà ouvert par un autre programme, il se déclenche généralement une erreur (sauf si on l'ouvre en Binaire, c'était le cas en VB6, c'est à vérifier en VB.NET).

Pour ouvrir un fichier on utilise FileOpen

FileOpen (FileNumber, FileName, Mode, Access, Share, RecordLength)

Paramètres de FileOpen

FileNumber
A tous fichier est affecté un numéro unique, c'est ce numéro que l'on utilisera pour indiquer sur quel fichier pratiquer une opération.. Utilisez la fonction FreeFile pour obtenir le prochain numéro de fichier disponible.
FileName
Obligatoire. Expression de type String spécifiant un nom de fichier. Peut comprendre un nom de répertoire ou de dossier, et un nom de lecteur.
Mode
Obligatoire. Énumération OpenMode spécifiant le mode d'accès au fichier : Append, Binary, Input (séquentiel en lecture), Output (séquentiel en écriture) ou Random (accès aléatoire).
Access
Facultatif. Mot clé spécifiant les opérations autorisées sur le fichier ouvert : Read, Write ou ReadWrite. Par défaut, la valeur est OpenAccess.ReadWrite
Share
Facultatif.  Spécifiant si un autre programme peut avoir en même temps accès au même fichier : Shared (permet l'accès aux autres programmes), Lock Read (interdit l'accès en lecture), Lock Write (interdit l'accès en écriture) et Lock Read Write (interdit totalement l'accès). Le processus OpenShare.Lock Read Write est paramétré par défaut.
RecordLength
Facultatif. Nombre inférieur ou égal à 32 767 (octets). Pour les fichiers ouverts en mode Random, cette valeur représente la longueur de l'enregistrement. Pour les fichiers séquentiels, elle représente le nombre de caractères contenus dans la mémoire tampon.

Pour écrire dans un fichier on utilise

Print , Write, WriteLine. dans les fichiers séquentiels

FilePut  dans les fichiers aléatoires

Pour lire dans un fichier on utilise:

Input, LineInput dans les fichiers séquentiels

FileGet dans les fichiers aléatoires.

Pour fermer le fichier on utilise FileClose()

Numéro de fichier:

Pour repérer chaque fichier, on lui donne un numéro unique (de type Integer).

La fonction FreeFile retourne le premier numéro libre.

Dim No as Integer

No= Freefile()

Ensuite on peut utiliser No pour repérer le fichier sur lequel on travaille.

FileOpen( No, "MonFichier", OpenMode.Output)

Print(No,"toto")

FileClose (No)

 

Fichier séquentiel:

Vous devez spécifier si vous voulez lire (entrer) des caractères issus du fichier (mode Input), écrire (sortir) des caractères vers le fichier (mode Output) ou ajouter des caractères au fichier (mode Append).

Ouvrir le fichier 'MonFichier' en mode séquentiel pour y écrire:

Dim No as integer

No= Freefile

FileOpen( No, "MonFichier", OpenMode.Output)

Pour écrire dans le fichier séquentiel: on utilise Write ou WriteLine Print ou PrintLine:

Print(1,"toto")

Print(1,"tata")

Print(1, 1.2)

Donne le fichier 'tototata1.2'

Write(1,"toto")

Write(1,"tata")

Write(1, 1.2)

Donne le fichier '"toto";"tata";1.2"

 

Attention s'il y a des points-virgules dans les chaînes , elles seront considérées comme séparateurs!! ce qui entraîne des erreurs à la lecture; il faut mettre la chaîne entre "" ou bien  remplacer le point-virgule par un caractère non utilisé (# par exemple) avant de l'enregistrer puis après la lecture remplacer '#' par ';'

 

Il faut utiliser Input pour relire ces données (Input utilise aussi le point-virgule comme séparateur.

WriteLine(1,"toto")

WriteLine(1,"tata")

WriteLine(1, 1.2)

Donne le fichier

"toto"

"tata"

1.2

Il faut utiliser LineInput pour relire ces données car il lit jusqu'au  retour Chariot, saut de ligne.

Toutes les données écrites dans le fichier à l'aide de la fonction Print respectent les conventions internationales ; autrement dit, les données sont mises en forme à l'aide du séparateur décimal approprié. Si l'utilisateur souhaite produire des données en vue d'une utilisation par plusieurs paramètres régionaux, il convient d'utiliser la fonction Write

 

EOF (NuméroFichier) veut dire 'End Of File', (Fin de Fichier) il prend la valeur True si on est à la fin du fichier et qu'il n'y a plus rien à lire.

LOF (NuméroFichier) veut dire 'Lenght Of File', il  retourne la longueur du fichier.

 

Exemple: Lire chaque ligne d'un fichier texte.

Dim Line As String
FileOpen(1, "MonFichier.txt", OpenMode.Input)
' Ouvre en lecture.
While Not EOF(1)
' Boucler jusqu'à la fin du fichier

Line = LineInput(1) ' Lire chaque ligne
Debug.WriteLine(Line)
' Afficher chaque ligne sur la console.

 

End While
FileClose(1)
' Fermer
.
 

Ici on a utilisé une boucle While.. End While qui tourne tant que EOF est Faux. Quand on est à la fin du fichier EOF (End of File)devient égal à True et on sort de la boucle.

 

Fichier à accès aléatoire:

On ouvre le fichier avec FileOpen et le mode OpenMode.Random, ensuite on peut écrire un enregistrement grâce à FilePut()  ou en lire un grâce à FileGet(). On peut se positionner sur un enregistrement précis (le 2eme, le 15ème) avec Seek.

Le premier enregistrement est l'enregistrement numéro 1

Exemple:

Fichier des adresses

Créer une structure Adresse, on utilise <VBFixedString( )> pour fixer la longueur.
 

Public Structure Adresse

   <VBFixedString(20)>Dim Nom        As String

   <VBFixedString(20)>Dim Rue        As String

   <VBFixedString(20)>Dim Ville      As String

End Structure

 

'Ouvrir le fichier, comme il n'existe pas, cela entraîne sa création
Dim FileNum As Integer, RecLength As Long,  UneAdresse As Adresse
' Calcul de la longueur de l'enregistrement
RecLength = Len(UneAdresse)
' Récupérer le premier numéro de fichier libre.
FileNum = FreeFile
' Ouvrir le fichier.
FileOpen(FileNum, "MONFICHIER.DAT", OpenMode.Random, , , RecLength)
 

Pour écrire des données sur le second enregistrement par exemple:

UneAdresse.Nom = "Philippe"

UneAdresse.Rue = "Grande rue"

UneAdresse.Ville = "Lyon"

FilePut(FileNum, UneAdresse,2 )

Dans cette ligne de code, FileNum contient le numéro utilisé par la fonction FileOpen pour ouvrir le fichier, 2 est le numéro de l'enregistrement ou sera copié la variable 'UneAdresse' (c'est un long si on utilise une variable) et UneAdresse, déclaré en tant que type Adresse défini par l'utilisateur, reçoit le contenu de l'enregistrement. Cela écrase l'enregistrement 2 s'il contenait quelque chose.

Pour écrire à la fin du fichier, ajouter un enregistrement il faut connaître le nombre d'enregistrement et écrire l'enregistrement suivant.

Dim last as long  'noter que le numéro d'enregistrement est un long

Pour connaître le nombre d'enregistrement, il faut diviser la longueur du fichier par la longueur d'un enregistrement.

last = FileLen("MONFICHIER.DAT") / RecLength

On ajoute 1 pour créer un nouvel enregistrement.

FilePut(FileNum, UneAdresse,last+1 )

Pour lire un enregistrement (le premier par exemple):
FileGet(FileNum, UneAdresse, 1)

Attention Option Strict doit être à  false .

Si option Strict est à True, la ligne qui précède génère une erreur car le second argument attendu ne peut pas être une variable 'structure'. Pour que le second argument de FileGet (Une adresse) soit converti dans une variable Structure automatiquement Option Strict doit donc être à false. (Il doit bien y avoir un moyen de travailler avec Option Strict On et  de convertir explicitement mais je ne l'ai pas trouvé)

Remarque: si le fichier contient 4 enregistrements, on peut écrire le 10ème enregistrement, VB ajoute entre le 4ème et le 10ème, 5 enregistrements vides. On peut lire un enregistrement qui n'existe pas, cela ne déclenche pas d'erreur.

Le numéro d'enregistrement peut être omis dans ce cas c'est l'enregistrement courant qui est utilisé.

On positionne l'enregistrement courant avec Seek:

Exemple: Lire le 8ème enregistrement:

Seek(FileNum,8)

FileGet(FileNum,Une Adresse)

Suppression d'enregistrements

Vous pouvez supprimer le contenu d'un enregistrement en effaçant ses champs (enregistrer à la même position des variables vides), mais l'enregistrement existe toujours dans le fichier.

Pour enlever un enregistrement supprimé

  1. Créez un nouveau fichier.
  2. Copiez tous les enregistrements valides du fichier d'origine dans le nouveau fichier (pas ceux qui sont vides).
  3. Fermez le fichier d'origine et utilisez la fonction Kill pour le supprimer.
  4. Utilisez la fonction Rename pour renommer le nouveau fichier en lui attribuant le nom du fichier d'origine.

Fichier binaire:

Dans les fichiers binaires on travaille sur les octets.

La syntaxe est la même que pour les fichiers Random, sauf qu'on travaille sur la position d'un octet et non sur un numéro d'enregistrement.

Pour ouvrir un fichier binaire:

FileOpen(FileNumber, FileName, OpenMode.Binary)
 

FileGet et FilePut permettent de lire ou d'écrire des octets .

FileOpen(iFr, ReadString, OpenMode.Binary)
MyString = New String(" "c, 15)       
'Créer une chaîne de 15 espaces
FileGet(iFr, MyString)                
' Lire 15 caractères dans MyString
FileClose(iFr)
MsgBox(MyString)

Le fait de créer une variable de 15 caractères et de l'utiliser dans FileGet permet de lire 15 caractères.
 

 

C-Utilisation du Contrôle RichTextBox.

On rappelle que du texte présent dans un contrôle RichTextBox peut être enregistré ou lu très simplement avec les méthodes .SaveFile et .LoadFile.

Le texte peut être du texte brut ou du RTF.

richTextBox1.SaveFile(FileName, RichTextBoxStreamType.PlainText)

Si on remplace .PlainText par .RichText c’est le texte enrichi et non le texte brut qui est enregistré

Pour lire un fichier il faut employer .LoadFile avec la même syntaxe.

Simple, non!!!

 

Lire ou écrire des octets ou du XML:

BinaryWriter et BinaryReader   permettent d'écrire ou de lire des données binaires.

XMLTextWriter et XMLTextReader  écrit et lit du Xml.

 

Pour enregistrer un tableau, un objet, Vb.Net propose aussi la Sérialization (voir ce chapitre)

 

D- Comment ouvrir une boite de dialogue pour ouvrir un fichier?

 

Ajouter un  contrôle OpenFileDialog à la form. (le nommer DialogOpen)  

 

With DialogOpen

.InitialDirectory = "C:\LDF"            'répertoire sur lequel s'ouvrira la boite

.Title = "Choisir une fichier"          'titre de la barre  

.Filter = "Fichiers LDF(*.ldf)|*.ldf"   'filtre, seules les fichiers LDF apparaîtront

.ShowDialog()                           ' on ouvre la boite de dialogue enfin

                                                                                 'Retour après la fermeture de la boite de dialogue

If Err.Number = 32755 Then Exit Sub     'le bouton 'annuler' a t'il été cliqué?

If Len(.FileName) = 0 Then  Exit Sub     'aucun choix

sFile = .FileName                       'nom du fichier choisi ( avec extension)

End With

Vous avez le nom du fichier a ouvrir, a vous de l'ouvrir avec un Open...

SaveFileDialog existe aussi.

 

 

Comment enregistrer, lire , effacer  une variable structurée dans un fichier binaire: 

Sans utiliser de FileOpen FilePut, FileGet mais en utilisant plutôt des FileStream (un BinaryReader et un BinaryWriter). On reste dans le Framework .Net et la programmation Objet.

Par Bruno Chappe.

Débutant s'abstenir.

Cette syntaxe est entièrement écrite en VB .NET 2005, et n’utilise que des objets avec méthodes et propriétés issue de VB .NET 2005.

On crée une Structure 'personne', une Class 'myBinaryReader', une Class 'myBinaryWriter' permettant de lire et d'enregistrer des 'personne'.

 

'System.IO doit être importé dans l'entête de votre module

ETAPE N°1 : Créer la structure et les classe binaryReader et binaryWriter personnalisées

'Créer la structure avec son constructeur spécifique

Structure personne

Public pNom As String

Public pPrenom As String

Public pAge As Integer

Public pMarie As Boolean

Sub New ( ByVal myNom As String , ByVal myPrenom As String , ByVal myAge As Integer , ByVal myMarie As Boolean )

Me.pNom = myNom

Me.pPrenom = myPrenom

Me.pAge = myAge

Me.pMarie = myMarie

End Sub

End Structure

 

'Créer une classe de binarywriter personnalisée à partir de le classe binarywriter native de vb

Class myBinarywriter

Inherits System.IO.BinaryWriter

Sub New ( ByVal st1 As System.IO.Stream )

MyBase.New(st1)

End Sub

'PadRight est utilisé pour faire des chaînes de caractère de longueur  fixes

'C'est indispensable pour pouvoir calculer la longueur des enregistrements par la suite et avoir des enregistrements qui ont tous la même longueur

Overloads Sub write( ByVal e As personne )

MyBase.Write(e.pNom.PadRight(15))

MyBase.Write(e.pPrenom.PadRight(15))

MyBase.Write(e.pAge)

MyBase.Write(e.pMarie)

End Sub

End Class

 

'Créer une classe de binaryreader personnalisée à partir de la classe binaryreader native de vb

Class myBinaryreader

Inherits System.IO.BinaryReader

Sub New ( ByVal st2 As System.IO.Stream )

MyBase.New(st2)

End Sub

Function readpersonne() As personne

Dim pNom As String = MyBase.ReadString

Dim pPrenom As String = MyBase.ReadString

Dim pAge As Integer = MyBase.ReadInt32

Dim pMarie As Boolean = MyBase.ReadBoolean

readpersonne = New personne(pNom, pPrenom, pAge, pMarie)

End Function

End Class

 


ETAPE N° 2 : Utilisation des classes personnalisées

 

***Ecrire un enregistrement

 

DEBUT

'Variable string stockant le chemin d'accès au fichier

Dim myFile as String

'Si l'on veut écrire directement dans un enregistrement existant (plutôt que d'écrire à la suite du fichier)

'il faut au préalable récupérer la rang de l'enregistrement ou l'on veut commencer à écrire

'et multiplier ce rang par la longueur d'un enregistrement (en octets). Cette opération nous donne

'la position du premier octet à écrire dans le fichier.

'Pour mémoire, la longueur d'un enregistrement en octet est égale à la taille du fichier en octet

'divisé par le nombre d'enregistrements (Voir Annexe de ce document pour les explications)

Dim position As Integer

'Déclarer une variable de type 'personne' et assigner les valeurs voulues à ses champs

'Il est possible de travailler avec un tableau de structure, cela revient au même mais

'est moins indispensable qu'avant vu que l'on peut aller écrire et lire directement dans le fichier

Dim maPersonne As personne

With maPersonne

.pNom = 'valeur du champ

.pPrenom = 'valeur du champ

.pAge = 'valeur du champ

.pMarie = 'valeur du champ

End With

'Déclare le flux et le writer qui vont nous permettre d'écrire notre structure

'Bien faire attention aux propriétés FileMode et FileAccess en fonction des opérations

'que vous voulez effectuer

'Si vous voulez écrire l'enregistrement à la suite des autres :

Dim fs As FileStream = File.Open(myFile, FileMode.Append, FileAccess.Write, FileShare.None)

'Si vous voulez re-ecrire/modifier un enregistrement :

Dim fs As FileStream = File.Open(myFile, FileMode.Open, FileAccess.Write, FileShare.None)

'Dans les 2 cas, remarquez ici que nous instancions un objet issue de la classe que nous avons créé plus haut

'et non pas un objet issue des classes natives de vb

Dim bw As New myBinarywriter(fs)

'Nécessaire que si vous souhaitez écrire à un endroit précis dans le fichier

'Où position indique la position de début d'écriture dans le flux (fs) et SeekOrigin.Begin indiquant à partir de quel

'endroit du flux commencer la recherche de position

fs.Seek(position, SeekOrigin.Begin)

'Dans tous les cas, l'instruction ci-dessous écrit l'intégralité de notre structure sous forme binaire dans le fichier

bw.write(maPersonne)

'SURTOUT BIEN PENSER A FERMER LES FLUX ET WRITER

bw().Close

fs().Close

FIN


***Lire un enregistrement

DEBUT

'Variable string stockant le chemin d'accès au fichier

Dim myFile as String

'Déclarer la variable qui va recevoir les informations issues du fichier

Dim maPersonne As personne

'Instancier un objet flux et un objet binaryReder

'Remarquez le FileAcces.Read pour la lecture

Dim fs As FileStream = File.Open(myFile, FileMode.Open, FileAccess.Read, FileShare.None)

'Objet instancié à partir de notre classe personnalisée myBinaryreader

Dim br As New myBinaryreader(fs)

'Si besoin d'aller lire un enregistrement précis

fs.Seek(position, SeekOrigin.Begin) 'Mêmes paramètres que pour l'écriture

'Sinon, vous ferez probablement un traitement en boucle de tout les enregistrements du fichier

Do Until fs.Position = fs.Length 'Faire jusqu'à ce que la position dans le flux soit égale à la longueur total du flux

myPersonne = br.readpersonne

'Ici traitez les informations récupérées, par exemple pour afficher dans un listBox

Loop

'SURTOUT BIEN PENSER A FERMER LES FLUX ET READER

br().Close

fs().Close

FIN


***Supprimer un enregistrement

‘Au préalable il faut “marquer” l’enregistrement à effacer en utilisant la procédure décrite plus haut pour modifier un enregistrement. Pour cela on peut faire soit comme dans le TP en utilisant un champ « supprimé »de notre structure que l’on marque à True soit on écrit un enregistrement vide par-dessus l’enregistrement que l’on veut effacer (en affectant « Nothing » au premier champ de l’enregistrement par exemple). En résumé, n’importe quoi qui nous permet de repérer au moment de la réécriture du fichier, que cet enregistrement ne doit pas être recopié.

 

‘Commencer par créer une copie du fichier original (Ne pas oublier de faire des tests sur l’existence du fichier)

Dim fi As New FileInfo(myFile)

Dim newFile As String = myFile & “.bck”

fi.CopyTo(newFile) ‘Créé newFile et copie myFile dedans

‘Ensuite on ouvre les 2 flux (1 en lecture et 1 en écriture) et les 2 binary (-reader & -writer)

Dim fsR As FileStream = File.Open(newFile, FileMode.Open, FileAccess.Read, FileShare.None)

‘Ici le le paramètre FileMode.Create va faire que le fichier myFile va être recréé par-dessus l’ancien fichier et l’écraser

Dim fsW As FileStream = File.Open(myFile, FileMode.Create, FileAccess.Write, FileShare.None)

‘Après l’instruction ci-dessus on a donc un fichier myFile qui existe mais qui est vide (sans avoir besoin de le supprimer d’abords et de le recréer ensuite), prêt à recevoir les données du fichier newFile.

Dim br As New myBinaryreader(fsR)

Dim bw As New myBinarywriter(fsW)

‘On dimensionne une variable du type de notre structure

Dim maPersonne As personne

‘Faire une boucle sur le fichier en lecture

Do Until fsR.Position = fsR.Length

maPersonne = br.readpersonne

‘Si marquage de maPersonne n’indique pas qu’il faut effacer l’enregistrement alors :

bw.write(maPersonne)

End If

Loop

‘Cette boucle va donc lire chaque enregistrement dans newFile, l’affecter dans une variable structurée maPersonne et si cette variable ne contient pas d’indicateur de suppression, l’écrire dans myFile. A la fin de la boucle myFile contient donc tous les enregistrements de newFile sauf ceux marqués à supprimer.

‘On oubli pas de fermer les flux

br.Close()

bw.Close()

fsR.Close()

fsW.Close()

‘Et de supprimer le fichier newFile qui ne nous sert plus à rien

File.Delete(newFile)


ANNEXE : Comment calculer la valeur de la variable « position » utilisée dans la méthode seek de notre FileStream

 

Nous avons besoin de 3 éléments : la longueur totale du fichier en octets, la taille d’un enregistrement en octets, le numéro de l’enregistrement que l’on souhaite modifier/remplacer/effacer.

 

Longueur totale du fichier en octets

Dim fi as New FileInfo(myFile)

Dim longueurFichier As Long

longueurFichier = fi.length ‘Renvoi un entier long représentant la taille totale en octet

Taille d’un enregistrement en octets

Dim nbEnreg As Integer ‘Au préalable il faut récupérer le nombre d’enregistrements, par exemple lors d’une première lecture du fichier séquentielle, en incrémentant un compteur par programmation.

Dim tailleEnreg as Integer

tailleEnreg = longueurFichier / nbEnreg

Pointer directement dans le fichier à l’octet voulu pour l’écriture

Autrement dit, calculer la variable « position » pour pouvoir l’utiliser dans la méthode seek.

Il suffit de multiplier le numéro de l’enregistrement à écrire (le premier enregistrement doit avoir  l’indice 0) par la taille d’un enregistrement.

Ainsi par exemple, si j’ai un fichier de 120 octets avec 12 enregistrements (de 0 à 11), cela me fait des enregistrements de 10 octets de long. Si je veux aller modifier le 4ème enregistrement, ma variable position sera égale à 40 (4*10).

Il ne me reste plus qu’à déplacer le pointeur dans mon flux avant d’écrire ma variable, en utilisant :

            fs.Seek(position, SeekOrigin.Begin)