FAQ Delphi .NET
FAQ Delphi .NETConsultez toutes les FAQ
Nombre d'auteurs : 15, nombre de questions : 54, dernière mise à jour : 16 juin 2021
- Comment récupérer le nom d'un fichier, lorsque j'ai le chemin complet ?
- Comment créer, copier, déplacer, supprimer un fichier ?
- Comment obtenir les attributs d'un fichier ou d'un répertoire?
- Comment obtenir la liste des fichiers et des sous-répertoires d'un répertoire ?
- Comment lire et écrire dans un fichier texte (StreamReader) ?
- Comment afficher ou écrire correctement les caractères accentués dans mes fichiers ?
- Comment lire et écrire dans un fichier texte (Text) ?
- Comment lire et écrire dans un fichier texte (TOpenedFile) ?
- Comment lire et écrire dans un fichier binaire ?
- Comment surveiller les modifications d'un fichier grâce aux notifications système?
Vous devez utiliser la méthode GetFileName de la classe System.IO.Path qui vous permet de récupérer le nom du fichier.
uses
System.IO;
var
filename : String
;
name : String
;
begin
fileName := 'C:\toto.txt'
;
name := System.IO.Path.GetFileName(fileName);
Console.WriteLine(name);
Pour créer, copier, déplacer ou supprimer un fichier, on utilise les méthodes de la classe System.IO.File.
uses
System.IO;
{$APPTYPE CONSOLE}
procedure
FileTests;
const
Source='C:\Temp\MonFichier.txt'
;
Destination='C:\Temp\Copy de MonFichier.txt'
;
Deplace='C:\Temp\MonFichierDéplacé.txt'
;
var
Fichier : FileStream ;
begin
try
With
System.IO.File
do
begin
//Création d'un fichier vide.
Fichier := &Create(Source) ;
Fichier.Close;
Console.WriteLine('Fichier {0} créé.'
,Source);
// Copie de fichier
Copy(Source, Destination);
Console.WriteLine('Fichier {0} copié vers {1}.'
,[Source,Destination]);
// Déplacement de fichier
Move(Destination, Deplace);
Console.WriteLine('Fichier {0} déplacé vers {1}.'
,[Destination,Deplace]);
// Suppression de fichier
Delete(Destination);
Console.WriteLine('Fichier {0} supprimé.'
,[Destination]);
end
;
except
on
ex : System.IO.IOException do
begin
Console.WriteLine(Environment.Newline+'Erreur : '
+ex.Message
);
Console.WriteLine(Environment.Newline+Environment.Newline+'Détails de l''exception :'
);
Console.WriteLine(ex.ToString);
end
;
end
;
end
;
Lien : System.IO.File
On utilise la méthode GetAttributes de la classe System.IO.File.
uses
System.IO;
procedure
GetFileAttributes(NomFichier : String
) ;
// Test : GetFileAttributes('C:\IO.SYS');
var
flagAttr : FileAttributes;
unAttr : System.IO.FileAttributes;
DateFichier : System.DateTime;
begin
With
System.IO.File
,DateFichier do
begin
flagAttr := GetAttributes(NomFichier);
// Date de création
DateFichier:=GetCreationTime(NomFichier);
Console.WriteLine('Créé le {0} à {1}'
,ToShortDateString,ToShortTimeString);
// Date de la dernière modification
DateFichier:=GetLastWriteTime(NomFichier);
Console.WriteLine('Modifié le {0} à {1}'
,ToShortDateString,ToShortTimeString);
// Date du dernier accès
DateFichier:=GetLastAccessTime(NomFichier);
Console.WriteLine('Dernier accès le {0} à {1}'
,ToShortDateString,ToShortTimeString);
Console.WriteLine('Attributs de {0}'
, NomFichier);
//Itération sur l'énumération
for
UnAttr in
Enum.GetValues(TypeOf(System.IO.FileAttributes)) do
if
( (flagAttr and
unAttr) = UnAttr)
then
Console.WriteLine(UnAttr);
// Il est possible de tester les attributs par le test suivant
// if ((flagAttr and FileAttributes.Archive) = FileAttributes.Archive)
// then Console.WriteLine(FileAttributes.Archive);
end
;
end
;
Lien : System.IO.File
On utilise la fonction GetFileSystemEntries de la classe System.IO.Directory.
uses
System.IO;
procedure
ScanDir(MonRepertoire : String
);
var
Fichiers : array
of
String
;
I : Integer
;
begin
// Obtient les noms des fichiers et sous-répertoires du répertoire MonRepertoire
Fichiers:= System.IO.Directory.GetFileSystemEntries(MonRepertoire);
for
i:=0
to
Length(Fichiers)-1
do
Console.WriteLine(Fichiers[i]);
end
;
Pour obtenir uniquement les noms des fichiers et pas les sous-répertoires d'un répertoire, on utilise la méthode System.IO.Directory.GetFiles.
Lien : System.IO.Directory
Nous allons ouvrir un fichier texte et le créer s'il n'existe pas.
Nous afficherons ensuite son contenu à l'écran.
On utilise pour cela les classes System.IO.StreamReader pour la lecture et System.IO.StreamWriter pour l'écriture.
procedure
FichierTexte(nomFichier : TFileName);
var
Lecteur : StreamReader ;
Ecrivain : StreamWriter ;
Ligne : String
;
begin
try
if
not
FileExists(nomFichier) then
begin
// Le fichier n'existe pas. On le crée.
Ecrivain := StreamWriter.Create(nomFichier);
Ecrivain.WriteLine('Bonjour. Nous sommes le {0} et il est {1} '
,
DateTime.Now.ToLongDateString(),
DateTime.Now.ToLongTimeString());
Ecrivain.Close;
// Remarque : on peut ajouter du texte à un fichier existant par
// Ecrivain:= File.AppendText(NomFichier);
end
;
// Ouverture du fichier et écriture du contenu du fichier sur la console
Console.WriteLine('Début du fichier'
);
Lecteur := StreamReader.Create( nomFichier );
Ligne := Lecteur.ReadLine;
while
ligne <> nil
do
begin
Console.WriteLine(ligne);
ligne := Lecteur.ReadLine;
end
;
Console.WriteLine( 'Fin du fichier'
);
finally
// Fermeture streamreader
if
Assigned(Lecteur)
then
Lecteur.Close;
// Fermeture streamwriter
if
Assigned(Ecrivain)
then
Ecrivain.Close;
end
;
end
;
begin
With
System.String
,System.Environment do
Filename:=Concat(IncludeTrailingBackslash(GetEnvironmentVariable('TEMP'
)),'Test.txt'
);
FichierTexte(Filename);
end
.
Lien : System.IO.StreamWriter
Lien : System.IO.StreamReader
Lien : Comment afficher ou écrire correctement les caractères accentués dans mes fichiers ?
Sous .NET les fichiers sont ouverts avec l'encodage unicode par défaut. Il en résulte que les caractères accentués par exemple ne s'affichent pas correctement. Vous devez spécifier le type d'encodage à utiliser, pour la lecture/écriture de votre fichier.
Exemple :
Uses
System.Text;
begin
Ecrivain := StreamWriter.Create(nomFichier,False
,Encoding.Default
);
...
Lecteur := StreamReader.Create(nomFichier,Encoding.Default
);
Ici on récupère l'encodage courant,Encoding.Default correspondant à la page de code active, et on l'applique lors de la création/ouverture du fichier par le StreamWriter. Dans ce cas les lectures, de ce même fichier, doivent se faire en utilisant le même encoding.
Sans préciser Encoding.Default :
- les caractères sont codés sur 2 octets
- 2 octets sont ajoutés en début de fichier (byte order mark (BOM) : Retourne un jeu d'octets utilisé au début d'un flux pour déterminer le codage avec lequel un fichier a été créé.
Lien : Comment lire et écrire dans un fichier texte (StreamReader) ?
Il est tout à fait possible d'utiliser la classe Borland.Delphi.System.Text qui permet d'utiliser la syntaxe héritée du Turbo Pascal.
L'instruction Writeln autorisant l'écriture d'une liste de paramètres n'est plus supportée. L'appel de la méthode Flush est ici obligatoire afin de forcer l'écriture du tampon dans le fichier.
L'instruction Readln autorisant la lecture d'une chaîne de caractères n'est plus supportée.
La gestion des erreurs se fait via l'appel à la fonction IOResult.
procedure
FichierTexte(nomFichier : TFileName);
var
Fichier : Text;
Ligne : String
;
begin
Assign(Fichier,NomFichier);
if
not
FileExists(nomFichier) then
begin
Rewrite(Fichier);
Ligne:='Nous sommes le '
+DateTime.Now.ToLongDateString+' et il est '
+DateTime.Now.ToLongTimeString;
Fichier.WriteAnsiString(Ligne,length(Ligne));
Fichier.Flush;
Close(Fichier);
// Remarque : on peut ajouter du texte à un fichier existant par
// Append(Fichier);
end
;
// Ouverture du fichier et écriture du contenu du fichier sur la console
Writeln('Début du fichier'
);
Reset(Fichier);
Ligne := Fichier.ReadAnsiString;
while
ligne <> nil
do
begin
Writeln(ligne);
ligne := Fichier.ReadAnsiString;
end
;
Close(Fichier);
Writeln( 'Fin du fichier'
);
end
;
La Classe Text encapsule un objet lecteur et écrivain :
Text = class
Mode: Word
;
Flags: Word
;
Factory: ITextDeviceFactory;
Reader: System.IO.TextReader;
Writer: System.IO.TextWriter;
Filename: string
;
...
ITextDeviceFactory est responsable de l'initialisation des champs lecteur ou écrivain de l'objet Text, dans le mode approprié.
La méthode Close est fournis pour les dispositifs qui exigent des opérations additionnelles pour libérer des ressources.
Notez qu'un objet Text peut fermer le lecteur ou l'écrivain associé sans détruire l'objet Text lui-même.
Les résultats de fonction sont des codes d'erreur du runtime et zéro pour indiquer le succès.
ITextDeviceFactory = interface
function
Open(t: Text; Mode: Word
): Integer
;
function
Close(t: Text): Integer
;
end
;
L'unité Borland.Vcl.SysUtils propose le type TOpenedFile qui est un alias de la classe System.IO.FileStream et est utilisé en lieu et place d'un fichier classique Win32/Linux nécessitant un handle. Les fonctions liées au fichiers du CLR n'utilisent pas de handles.
De nombreuses fonctions encapsulent les opérations autour de la classe FileStream.
Voici les principales
Fileopen
FileOpen ouvre le fichier indiqué en utilisant le mode d'accès indiqué.
La valeur du mode d'accès est construite par une opération 'OR' à partir des constantes de fmOpenXXXX et des constantes de fmShareXXXX, exemple:
fmOpenRead or
fmShareDenyWrite.
Sous la CLR, FileOpen renvoie un objet de la classe FileStream, ou zéro si le fichier n'existe pas.
FileCreate
FileCreate crée un nouveau dossier avec le nom indiqué. Si la valeur de retour est différent de Nil, l'opération à réussie et la valeur retournée est un objet de la classe System.IO.FileStream avec l'accès en lecture/écriture.
Une valeur de retour Nil indique qu'une erreur s'est produite.
Seconde version de FileCreate
Une deuxième version de FileCreate est utilisée à des fins de compatibilité avec la fonction Linux qui vous permets d'indiquer les droits d'accès du nouveau fichier créé.
Le paramètre de droits d'accès est ignoré.
Fileread
FileRead lit Count octets à partir du fichier indiqué par Handle dans la zone indiquée par Buffer.
La valeur de retour est le nombre d'octets réellement lus; elle est inférieure à Count si la fin du fichier est atteinte.
La valeur de retour est -1 si une erreur se produit. Il existe une dizaine de méthodes FileRead surchargées.
FileWrite
FileWrite écrit Count octets dans le fichier indiqué par Handle à partir la zone indiquée par Buffer.
La valeur de retour est le nombre d'octets réellement écrits.
La valeur de retour est -1 si une erreur se produit. Il existe une dizaine de méthode FileWrite surchargées.
...
procedure
FichierTexte(nomFichier : TFileName);
var
Fichier : TOpenedFile ;
Lignes : String
;
S : String
;
LecteurChaine : StringReader;
begin
if
not
FileExists(nomFichier) then
begin
// Le fichier n'existe pas.
Fichier := FileCreate(nomFichier);// crée et ouvre le fichier
if
Assigned(Fichier) then
begin
With
DateTime.Now do
Lignes:=Format('Bonjour. Nous sommes le %s et il est %s '
,[ToLongDateString,ToLongTimeString]);
if
FileWrite(Fichier, Lignes,Lignes.Length)=-1
then
Writeln('Erreur lors de l''écriture'
);
FileClose(Fichier);
// Remarque : on peut ajouter du texte à un fichier existant par
{
Fichier := FileOpen(nomFichier,(fmOpenReadWrite));
Position:=FileSeek(Fichier,0,2);
Lignes:=Environment.NewLine+Lignes;
NbOctetEcris:=FileWrite(Fichier,Lignes,Lignes.Length);
FileClose(Fichier);
}
end
;
end
;
// Ouverture du fichier et écriture du contenu du fichier sur la console
Console.WriteLine('Début du fichier'
);
Fichier := FileOpen(nomFichier,(fmOpenReadWrite));
if
Assigned(Fichier) then
begin
if
FileRead(Fichier,Lignes, Fichier.Length)=-1
then
Writeln('Erreur lors de la lecture'
);
FileClose(Fichier);
LecteurChaine:=StringReader.Create(Lignes);
Repeat
S:=LecteurChaine.ReadLine; // Pour un saut de ligne dans un texte, readline renvoi S=''=Nil
Console.WriteLine(S);
// Test s'il reste qq chose à lire, un saut de ligne est considéré comme 'qq chose à lire'
Until
LecteurChaine.Peek=-1
;
LecteurChaine.Close;
end
;
Console.WriteLine( 'Fin du fichier'
);
end
;
Pour la lecture, en utilisant la méthode FileWrite, il est difficile de connaître par avance le nombre d'octets à lire. On peut donc lire l'intégralité du fichier texte et le placer dans une chaîne de caractères (String).
Ensuite on utilise un objet de la classe StringReader pour lire ligne par ligne (séparateur Carriage_return+Line_feed) le texte précédemment placer dans une chaîne de caractères.
La détection de la fin de fichier se fait par l'appel de la méthode Peek qui renvoi -1 s'il n'y a plus de caractère à lire.
Lien : La classe StringReader
Lien : La classe StringWriter
On utilise pour cela les classes System.IO.BinaryReader pour la lecture et System.IO.BinaryWriter pour l'écriture.
Nous allons ouvrir un fichier binaire ou le créer s'il n'existe pas encore, puis nous y insérerons des nombres de type integer. Ensuite nous afficherons son contenu à l'écran.
BinaryWriter :
Écrit des types primitifs en binaire dans un flux et prend en charge l'écriture de chaînes dans un codage spécifique.
BinaryReader :
Lit les types de données primitifs comme des valeurs binaires dans un codage spécifique.
Leur usage impose donc d'utiliser un seul type de donnée.
Contenu du fichier avec une variable i de type Integer
01 00 00 00 02 00 00 00-03 00 00 00 04 00 00 00
05 00 00 00 06 00 00 00-07 00 00 00 08 00 00 00
Contenu du fichier avec une variable i de type Byte
01 02 03 04 05 06 07 08-09 0A
Il est possible de réduire l'occupation disque en utilisant la méthode Write7BitEncodedInt qui écrit un nombre entier 32 bits dans un format compressé.
procedure
TestFichierBinaire(NomFichier : String
) ;
var
//i : integer;
i : Byte
;
LecteurBinaire : BinaryReader;
EcrivainBinaire : BinaryWriter;
Fichier : FileStream;
begin
try
if
not
FileExists(NomFichier) then
begin
Console.WriteLine('Ecriture du fichier'
);
// Le fichier n'existe pas. On le crée
Fichier:=System.IO.File
.&Create(NomFichier);
EcrivainBinaire := BinaryWriter.Create(Fichier);
//EcrivainBinaire := System.IO.BinaryWriter.Null;
for
i:=1
to
10
do
// Écrit un entier non signé dans le flux actuel et avance la position du flux du nombre d'octet
// correspondant à la taille du type écrit.
EcrivainBinaire.Write
(i);
//EcrivainBinaire.Write(Nomfichier); // Ecrit un tableau de Byte
EcrivainBinaire.Close;
end
;
Console.WriteLine('Lecture du fichier'
);
// Ouverture du contenu du fichier et écriture sur la console
Fichier := System.IO.File
.Open(NomFichier, FileMode.Open);
LecteurBinaire := BinaryReader.Create(Fichier);
while
(Fichier.Position < Fichier.Length) do
//Console.Writeline('{0}',[LecteurBinaire.ReadInt32]);
Console.Writeline('{0}'
,[LecteurBinaire.ReadByte]);
Console.WriteLine(Environment.NewLine+'Fin du fichier'
);
finally
if
Assigned(LecteurBinaire)
then
LecteurBinaire.Close; //Ferme le BinaryReader et le flux associé
if
Assigned(EcrivainBinaire)
then
EcrivainBinaire.Close; //Ferme le BinaryWriter et le flux associé
end
;
end
;
On peut utiliser un BinaryWriter sans magasin de sauvegarde en utilisant le champ de classe Null :
EcrivainBinaire := BinaryWriter.Null;
Et ce à la place de :
EcrivainBinaire := BinaryWriter.Create(Fichier);
Dans ce cas les écritures se font dans un flux simulé.
Lien : System.IO.BinaryReader
Lien : System.IO.BinaryWriter
Sous .NET il est possible de surveiller plus facilement les modifications apportées au système de fichier.
La classe System.IO.FileSystemWatcher écoute les notifications de modifications du système de fichiers et déclenche un événement lorsqu'un répertoire ou un fichier d'un répertoire est modifié.
Nous vous invitons à lire la documentation du SDK associée à cette classe. Consultez l'url de la section Lien.
Dans un premier temps déclarons les méthodes associées aux événements qu'on souhaite intercepter :
procedure
OnChanged( Source : TObject ; E : FileSystemEventArgs) ;
begin
Console.WriteLine('[Notification]Fichier {0} {1}'
, E.FullPath, E.ChangeType);
Console.WriteLine;
end
;
procedure
OnRenamed( Source : TObject ; E : RenamedEventArgs ) ;
begin
Console.WriteLine('[Notification]Fichier {0} renommé en {1}'
, E.OldFullPath, E.FullPath);
Console.WriteLine;
end
;
procedure
OnError(Source : TObject ; E : ErrorEventArgs) ;
begin
Console.WriteLine('[Notification]Erreur'
+ E.GetException.ToString);
Console.WriteLine;
end
;
Il est possible de redéfinir les modifications à observer en utilisant l'enumération NotifyFilters.
Ensuite il nous faut configurer une instance de FileSystemWatcher :
Function
Watch(Path : String
; Filtre : String
): FileSystemWatcher;
// Surveille les modifications survenues au sein du répertoire Path mais pas celles apportées au répertoire lui-même.
begin
// si Filtre='*.txt' Surveille tous les fichiers portant l'extension .txt
// si Filtre='' Surveille tous les fichiers (par défaut).
// Création de l'objet watcher
Result := FileSystemWatcher.Create(Path, Filtre);
// On ajoute les handlers pour surveiller les événements souhaités.
With
Result do
begin
// limite le nombre de modifications de fichier ou de répertoire pour lesquelles
// l'instance du composant déclenche des événements.
//NotifyFilter:= NotifyFilters.Attributes;
Include( Changed, OnChanged );
Include( Renamed, OnRenamed );
Include( Created, OnChanged );
Include( Deleted, OnChanged );
Include( Error, OnError );
// On surveillera aussi les sous-répertoires existant et ceux qui seront créés
IncludeSubdirectories := True
;
// Affecter EnableRaisingEvents à true démarre la surveillance des modifications.
EnableRaisingEvents := True
;
// Affecter EnableRaisingEvents à false arrête la surveillance des modifications.
end
;
end
;
Et voici l'utilisation de la fonction Watch :
// Pour surveiller l'activité sur les fichier *.txt du répertoire c:\temp
var
FichierSurveille : FileSystemWatcher;
begin
FichierSurveille:=Watch('c:\temp'
,'*.txt'
);
Filetests; // Voir la QR citée dans la section Lien
readln;
FichierSurveille.EnableRaisingEvents := False
;
readln;
Les instructions Readln vous permettront d'intervenir sur le répertoire en utilisant l'explorateur de fichier par exemple.
Lien : Introduction à la surveillance des événements de système de fichiers
Lien : System.IO.FileSystemWatcher
Lien : Comment créer, copier, déplacer, supprimer un fichier ?