1.1 La manipulation des répertoires
1.2 La manipulation des chemins d'accès disque
1.3 La manipulation des fichiers
2. Flux et fichiers dans NetFramework
2.1 Les flux avec C#3. Exercice de fichier de salariés avec une IHM
2.2 Les flux et les fichiers de caractères avec C#
2.3 Création d'un fichier de texte avec des données
2.4 Copie des données d'un fichier texte dans un autre
Différences entre flux et fichiers
- Un fichier est une ensemble de données structurées possédant un nom (le nom du fichier) stockées généralement sur disque (dans une mémoire de masse en général) dans des enregistrement sous forme d'octets. Les fichiers sont en écriture ou en lecture et ont des organisations diverses comme l'accès séquentiels, l'accès direct, l'accès indexé, en outre les fichiers sont organisés sur le disque dans des répertoires nommés selon des chemins d'accès.
- Un flux est un tube de connexion entre deux entrepôts pouvant contenir des données. Ces entités entreposant les données peuvent être des mémoire de masse (disques) ou des zones différentes de la mémoire centrale, ou bien des réseaux différents (par exemple échanges de données entre sockets).
- En C#, il faut utiliser un flux pour accèder aux données d'un fichier stocké sur disque, ce flux connecte les données du fichier sur le disque à une zone précise de la mémoire : le tampon mémoire.
Le Framework.Net dispose d'une famille de classes permettant la manipulation de données externes : System.IO
Espace de noms System.IO
- contient des classes qui permettent la lecture et l'écriture dans des fichiers,
- contient des classes qui permettent la lecture et l'écriture dans des flux ,
- contient des classes qui permettent la création, le renommage, le déplacement de fichiers et de répertoires sur disque.
1. Les manipulations disque de fichiers et de répertoires
L'espace de nom System.IO contient plusieurs classes de manipulation des fichiers et des répertoires. Certaines ne contiennent que des méthodes static (rassemblement de méthodes utiles à la manipulation de fichiers ou de répertoires quelconques), d'autres contiennet des méthodes d'instances et sont utiles lorsque l'on veut travailler sur un objet de fichier précis.
System.IO.Directory System.IO.DirectoryInfo
System.IO.File System.IO.FileInfo
System.IO.Path
1.1 La manipulation des répertoires
La classe System.IO.Directory hérite directement de System.Object et ne rajoute que des méthodes static pour la création, la suppression, le déplacement et le positionnement de répertoires :
CreateDirectory
Delete
Exists
GetAccessControl
GetCreationTime
GetCreationTimeUtc
GetCurrentDirectory
GetDirectories
GetDirectoryRoot
GetFiles
GetFileSystemEntries
GetLastAccessTime
GetLastAccessTimeUtc
GetLastWriteTime
GetLastWriteTimeUtc
GetLogicalDrives
GetParent
Move
SetAccessControl
SetCreationTime
SetCreationTimeUtc
SetCurrentDirectory
SetLastAccessTime
SetLastAccessTimeUtc
SetLastWriteTime
SetLastWriteTimeUtc
a) Création d'un répertoire sur disque, s'il n'existe pas au préalable :
string cheminRep = @"D:\MonRepertoire";
if ( !Directory.Exists( cheminRep )) {
Directory.CreateDirectory( cheminRep );
}
Ces 3 lignes de code créent un répertoire MonRepertoire à la racine du disque D.
b) Suppression d'un répertoire et de tous ses sous-répertoires sur disque :
string cheminRep = @"D:\MonRepertoire";
if ( Directory.Exists( cheminRep )) {
Directory.Delete( cheminRep, true );
}
Ces 3 lignes de code suppriment sur le disque D, le répertoire MonRepertoire et tous ses sous-répertoires.
c) Déplacement d'un répertoire et de tous ses sous-répertoires sur disque :
string cheminRep = "D:\\MonRepertoire";
string cheminDest = "C:\\NouveauRepertoire";
if ( Directory.Exists( cheminRep )) {
Directory.Move( cheminRep, cheminDest );
}
Ces 3 lignes de code déplacent le répertoire MonRepertoire et tous ses sous-répertoires du disque D vers le disque C sous le nouveau nom NouveauRepertoire.
d) Accès au répertoire disque de travail en cours de l'application :
string cheminRepAppli = Directory.GetCurrentDirectory( );
Attention, ce répertoire est le dernier répertoire en cours utilisé par l'application, il n'est pas nécessairement celui du processus qui a lancé l'application, ce dernier peut être obtenu à partir de la classe Application par la propriété "static string StartupPath" :
string cheminLancerAppli = Application.StartupPath ;
La classe System.IO.DirectoryInfo qui hérite directement de System.Object sert aussi à la création, à la suppression, au déplacement et au positionnement de répertoires, par rapport à la classe Directory, certaines méthodes sont transformées en propriétés afin d'en avoir une utilisation plus souple. Conseil de Microsoft : "si vous souhaitez réutiliser un objet plusieurs fois, l'utilisation de la méthode d'instance de DirectoryInfo à la place des méthodes static correspondantes de la classe Directory peut être préférable". Le lecteur choisira selon l'application qu'il développe la classe qui lui procure le plus de confort. Afin de bien comparer ces deux classes nous reprenonsavec la classe DirectoryInfo, les mêmes exemples de base de la classe Directory.
a) Création d'un répertoire sur disque, s'il n'existe pas au préalable :
string cheminRep = @"D:\MonRepertoire";
DirectoryInfo Repertoire = new DirectoryInfo( cheminRep );
if ( !Repertoire.Exists ) {
Repertoire.Create( );
}
Ces lignes de code créent un répertoire MonRepertoire à la racine du disque D.
b) Suppression d'un répertoire et de tous ses sous-répertoires sur disque :
string cheminRep = "D:\\MonRepertoire";
DirectoryInfo Repertoire = new DirectoryInfo( cheminRep );
if ( Repertoire.Exists ) {
Repertoire.Delete( true );
}
Ces lignes de code suppriment sur le disque D, le répertoire MonRepertoire et tous ses sous-répertoires.
c) Déplacement d'un répertoire et de tous ses sous-répertoires sur disque :
string cheminRep = @"D:\MonRepertoire";
string cheminDest = @"C:\NouveauRepertoire";
DirectoryInfo Repertoire = new DirectoryInfo( cheminRep );
if ( Repertoire.Exists ) {
Repertoire.MoveTo( cheminDest );
}
Ces lignes de code déplacent le répertoire MonRepertoire et tous ses sous-répertoires du disque D vers le disque C sous le nouveau nom NouveauRepertoire.
1.2 La manipulation des chemins d'accès disque
La classe System.IO.Path hérite directement de System.Object et ne rajoute que des méthodes et des champs static pour la manipulation de chaînes string contenant des chemins d'accès disque ( soit par exemple à partir d'une string contenant un chemin comme "c:\rep1\rep2\rep3\appli.exe", extraction du nom de fichier appli.exe, du répertoire c:\rep1\rep2\rep3, de l'extension .exe, etc... ).
Ci-dessous nous donnons quelques méthodes static pratiques courantes de la classe permettant les manipulations usuelles d'un exemple de chemin d'accès disque sous Windows :
string chemin = "C:\\rep1\\rep2\\appli.exe";
ou bien
string chemin = @"C:\rep1\rep2\appli.exe";
Appel de la méthode static sur la string chemin
résultat obtenu àprès l'appel
System.IO.Path.GetDirectoryName ( chemin )
System.IO.Path.GetExtension ( chemin )
System.IO.Path.GetFileName ( chemin )
System.IO.Path.GetFileNameWithoutExtension ( chemin )
System.IO.Path.GetFullPath ("C:\\rep1\\rep2\\..\\appli.exe")
System.IO.Path.GetPathRoot ( chemin )
C:\rep1\rep2
.exe
appli.exe
appli
C:\rep1\appli.exe
C:\
1.3 La manipulation des fichiers
La classe System.IO.File hérite directement de System.Object et ne rajoute que des méthodes static pour la manipulation, la lecture et l'écriture de fichiers sur disque :
AppendAll
AppendAllText
AppendText
Copy
Create
CreateText
Decrypt
Delete
Encrypt
Exists
GetAccessControl
GetAttributes
GetCreationTime
GetCreationTimeUtc
GetLastAccessTime
GetLastAccessTimeUtc
GetLastWriteTime
GetLastWriteTimeUtc
Move
Open
OpenRead
OpenText
OpenWrite
ReadAll
ReadAllBytes
ReadAllLines
ReadAllText
Replace
SetAccessControl
SetAttributes
SetCreationTime
SetCreationTimeUtc
SetLastAccessTime
SetLastAccessTimeUtc
SetLastWriteTime
SetLastWriteTimeUtc
WriteAll
WriteAllBytes
WriteAllLines
WriteAllText
Exemple de création d'un fichier et de ses répertoires sur le disque en combinant les classes Directory, Path et File :
string cheminRep = @"d:\temp\rep1\fichier.txt";
// création d'un répertoire et d'un sous-répertoire s'ils n'existent pas déjà
if ( !Directory.Exists( Path.GetDirectoryName(cheminRep ) ) )
Directory.CreateDirectory( Path.GetDirectoryName(cheminRep ) );
// effacer le fichier s'il existe déjà
if (File.Exists(cheminRep ))
File.Delete(cheminRep );
// création du fichier " fichier.txt " sur le disque D : dans " D:\temp\rep1"
FileStream fs = File.Create( cheminRep );
Les lignes de code C# précédentes créent sur le disque dur D: , les répertoires temp et rep1, puis le fichier.txt selon l'architecture disque ci-après :
D:
![]()
2. Flux et fichiers dans NetFramework
Une application travaille avec ses données internes, mais habituellement il lui est très souvent nécessaire d'aller chercher en entrée, on dit lire, des nouvelles données (texte, image, son,...) en provenance de diverses sources (périphériques, autres applications, zones mémoires...). Réciproquement, une application peut après traitement, délivrer en sortie des résultats, on dit écrire, dans un fichier, vers une autre application ou dans une zone mémoire. Les flux servent à connecter entre elles ces diverses sources de données.
![]()
En C# toutes ces données sont échangées en entrée et en sortie à travers des flux (Stream).
Un flux est une sorte de tuyau de transport séquentiel de données.
![]()
Il existe un flux par type de données à transporter :
![]()
Un flux est unidirectionnel : il y a donc des flux d'entrée et des flux de sortie.
L'image ci-après montre qu'afin de jouer un son stocké dans un fichier, l'application C# ouvre en entrée, un flux associé au fichier de sons et lit ce flux séquentiellement afin ensuite de traiter les sons (modifier ou jouer le son) :
![]()
La même application peut aussi traiter des images à partir d'un fichier d'images et renvoyer ces images dans le fichier après traitement. C# ouvre un flux en entrée sur le fichier image et un flux en sortie sur le même fichier, l'application lit séquentiellement le flux d'entrée (octet par octet par exemple) et écrit séquentiellement dans le flux de sortie :
![]()
D'une manière générale, NetFramework met à notre disposition dans l'espace de noms System.IO une classe abstraite de flux de données considérées comme des séquences d'octets, la classe System.IO.Stream. Un certain nombre de classes dérivent de la classe Stream et fournissent des implémentations spécifiques en particulier les classes :System.IO.FileStream, consacrée aux flux connectés sur des fichiers.
System.IO.MemoryStream, consacrée aux flux connectés sur des zones mémoires.
System.Net.Sockets.NetworkStream, consacrée aux flux connectés sur des accès réseau.
Entrées/Sorties synchrone - asynchrone
synchrone
Les accès des flux aux données ( lecture par Read ou écriture de base par Write ) sont par défaut en mode synchrone c'est à dire : la méthode qui est en train de lire ou d'écrire dans le flux elle ne peut exécuter aucune autre tâche jusqu'à ce que l'opération de lecture ou d'écriture soit achevée. Le traitement des entrées/sorties est alors "séquentiel".
asynchrone
Ceci peut être pénalisant si l'application travaille sur de grandes quantités de données et surtout lorsque plusieurs entrées/sorties doivent avoir lieu "en même temps", dans cette éventualité NetFramework fournit des entrées/sorties multi-threadées (qui peuvent avoir lieu "en même temps") avec les méthodes asynchrones de lecture BeginRead et EndRead et d'écriture BeginWrite et EndWrite ). Dans le cas d'utilisation de méthodes asynchrones, le thread principal peut continuer à effectuer d'autres tâches : le traitement des entrées/sorties est alors "parallèle".
Tampon ( Buffer )
Les flux du NetFramework sont tous par défauts "bufférisés" contrairement à Java. Dans le NetFramework, un flux (un objet de classe Stream) est une abstraction d'une séquence d'octets, telle qu'un fichier, un périphérique d'entrée/sortie, un canal de communication à processus interne, ou un socket TCP/IP. En C#, un objet flux de classe Stream possède une propriété de longueur Length qui indique combien d'octets peuvent être traités par le flux. En outre un objet flux possède aussi une méthode SetLength( long val ) qui définit la longueur du flux : cette mémoire intermédiaire associée au flux est aussi appelée mémoire tampon ( Buffer en Anglais) du flux.
Lorsqu'un flux travaille sur des caractères, on peut faire que l'application lise ou écrive les caractères les uns après les autres en réglant la longueur du flux à 1 caractère (correspondance avec les flux non bufférisés de Java) :
![]()
On peut aussi faire que l'application lise ou écrive les caractères par groupes en réglant la longueur du flux à n caractères (correspondance avec les flux bufférisés de Java) :
![]()
Nous allons plus particulièrement étudier quelques exemples d'utilisation de flux connectés sur des fichiers et plus précisément des fichiers de textes.
Eu égard à l'importance des fichiers comportant des données textuelles (à bases de caractères) le NetFramework dispose de classe de flux chargés de l'ecriture et de la lecture de caractères plus spécialisées que la classe System.IO.FileStream.
Les classes de base abstraites de ces flux de caractères se dénomment System.IO.TextReader pour la classe permettant la création de flux de lecture séquentielle de caractères et System.IO.TextWriter pour la classe permettant la création de flux d'écriture séquentielle de caractères.
Les classes concrètent et donc pratiques, qui sont fournies par NetFramework et qui implémentent ces deux classes abstraites sont :
System.IO.StreamReader qui dérive et implémente System.IO.TextReader.
System.IO.StreamWriter qui dérive et implémente System.IO.TextWriter.
2.3 Création d'un fichier de texte avec des données
Exemple d'utilisation des 2 classes précédentes.
Supposons que nous ayons l'architecture suivante sur le disque C:
![]()
Il est possible de créer un nouveau fichier sur le disque dur et d'ouvrir un flux en écriture sur ce fichier en utilisant le constructeur de la classe System.IO.StreamWriter :
StreamWriter fluxWrite = new StreamWriter(@"c:\temp\rep1\essai.txt");
Voici le résultat obtenu par la ligne de code précédente sur le disque dur :
![]()
Le programme C# ci-dessous permet de créer le fichier texte nommé essai.txt et d'écrire des lignes de texte dans ce fichier avec la méthode WriteLine(...) de la classe StreamWriter, puis de lire le contenu selon le schéma ci-après avec la méthode ReadLine( ) de la classe StreamReader :
![]()
Code source C# correspondant :
if (!File.Exists( @"c:\temp\rep1\essai.txt" )) {Console.WriteLine("Contenu du fichier essai.txt déjà présent :");
// création d'un fichier texte et ouverture d'un flux en écriture sur ce fichier
StreamWriter fluxWrite = new StreamWriter(@"c:\temp\rep1\essai.txt");
Console.WriteLine("Fichier essai.text créé sur le disque dur.");
Console.WriteLine("Il n'écrase pas les données déjà présentes");
// écriture de lignes de texte dans le fichier à travers le flux :
for ( int i = 1; i<10; i++)
fluxWrite.WriteLine("texte stocké par programme ligne N : "+i);
fluxWrite.Close( ); // fermeture du flux impérative pour sauvegarde des données
}
// création et ouverture d'un flux en lecture sur ce fichier
StreamReader fluxRead = new StreamReader(@"c:\temp\rep1\essai.txt");
// lecture des lignes de texte dans le fichier à travers le flux
string ligne;
while ( ( ligne = fluxRead.ReadLine()) != null )
Console.WriteLine(ligne);
fluxRead.Close();// fermeture du flux
2.4 Copie des données d'un fichier texte dans un autre
Nous utilisons l''instruction using qui définit un bloc permettant d'instancier un objet local au bloc à la fin duquelle un objet est désalloué.
Un bloc using instanciant un objet de flux en lecture :
using ( StreamReader fluxRead = new StreamReader( ...)) { ....BLOC.... }
Un bloc using instanciant un objet de flux en écriture :
using (StreamWriter fluxWrite = new StreamWriter( ...)) { ....BLOC.... }
Code source C# créant le fichier essai.txt :
Code source C# lisant le contenu du fichier essai.txt :if ( !File.Exists( @"c:\temp\rep1\essai.txt" )) {using (StreamWriter fluxWrite = new StreamWriter(@"c:\temp\rep1\essai.txt"))
{
Console.WriteLine("Fichier essai.text créé sur le disque dur.");
Console.WriteLine("Il n'écrase pas les données déjà présentes");
// écriture de lignes de texte dans le fichier à travers le flux :
for ( int i = 1; i<10; i++)
fluxWrite.WriteLine("texte stocké par programme ligne N : "+i);
} // fermeture et désallocation de l'objet fluxWrite
}
Console.WriteLine("Contenu du fichier 'essai.text' déjà présent :");
using ( StreamReader fluxRead = new StreamReader(@"c:\temp\rep1\essai.txt"))
{
string ligne;
// lecture des lignes de texte dans le fichier à travers le flux :
while ((ligne = fluxRead.ReadLine()) != null )
Console.WriteLine(ligne);
Console.WriteLine("\nRecopie en cours ...");
} // fermeture et désallocation de l'objet fluxRead
Code source C# recopiant le contenu du fichier essai.txt, créant le fichier CopyEssai.txt et recopiant le contenu de essai.txt :
using ( StreamReader fluxRead = new StreamReader(@"c:\temp\rep1\essai.txt"))
{
StreamWriter fluxWrite = new StreamWriter(@"c:\temp\rep1\CopyEssai.txt");
string ligne;
// on lit dans essai.txt à travers fluxRead et on écrit dans
// CopyEssai.txt à travers fluxWrite :
while ((ligne = fluxRead.ReadLine()) != null )
fluxWrite.WriteLine("copie < "+ligne+" >");
fluxWrite.Close();// fermeture de fluxWrite
}// fermeture et désallocation de l'objet fluxRead
Code source C# lisant le contenu du fichier CopyEssai.txt :
using ( StreamReader fluxRead = new StreamReader("copyEssai.txt"))
{
Console.WriteLine("\nContenu de la copie 'copyEssai.txt' :");
string ligne;
// lecture des lignes de texte du nouveau fichier copié fichier à travers le flux :
while ((ligne = fluxRead.ReadLine()) != null )
Console.WriteLine(ligne);
} // fermeture et désallocation de l'objet fluxRead
Résultat d'exécution du code précédent :
Contenu du fichier 'essai.text' déjà présent :
texte stocké par programme ligne N : 1
texte stocké par programme ligne N : 2
.....
texte stocké par programme ligne N : 9
Recopie en cours ...
Contenu de la copie 'copyEssai.txt' :
copie < texte stocké par programme ligne N : 1 >
copie < texte stocké par programme ligne N : 2 >
.....
copie < texte stocké par programme ligne N : 9 >
3. Exercice de fichier de salariés avec une IHM
Soit à écrire un programme C# gérant en saisie et en consultation un fichier des salariés d'une petite entreprise :
![]()
Ci-dessous les éléments à écrire en mode console d'abord, puis créez vous-mêmes une interface interactive.
Soit les diagrammes de classe suivants :
![]()
Le programme travaille sur des objets de classe Salarie :
![]()
Squelette et implémentation partielle des classes de base :
enum CategoriePerso
{
Cadre_Sup,Cadre,Maitrise,Agent,Autre
}
/// <summary>
/// Interface définissant les propriétés de position d'un
/// salarié dans la hiérarchie de l'entreprise.
/// </summary>
interface IPositionHierarchie
{
int Indice_Hierarchique
{
get ;
set ;
}
double Coeff_Prime
{
get ;
set ;
}
DateTime IndiceDepuis
{
get ;
set ;
}
} // fin interface IPositionHierarchie
/// <summary>
/// Classe de base abstraite pour le personnel. Cette classe n'est
/// pas instanciable.
/// </summary>
abstract class Salarie : IPositionHierarchie
{
/// attributs identifiant le salarié :
private int FCodeEmploye ;
private string FPrenom ;
private CategoriePerso FCategorie ;
private string FNom ;
private string FInsee ;
protected int FMerite ;
private int FIndice ;
private double FCoeffPrime ;
private double FBasePrime ;
private DateTime FIndiceDetenu ;
///le constructeur de la classe employé au mérite :
public Salarie ( int IDentifiant, string Nom, string Prenom, CategoriePerso Categorie,
string Insee, int Merite, int Indice, double CoeffPrime )
{
FCodeEmploye = IDentifiant ;
FNom = Nom ;
FPrenom = Prenom ;
FCategorie = Categorie ;
FInsee = Insee ;
FMerite = Merite ;
FIndice = Indice ;
FCoeffPrime = CoeffPrime ;
FIndiceDetenu = DateTime.Now ;
switch ( FCategorie )
{
case CategoriePerso.Cadre_Sup :
FBasePrime = 2000 ;
break;
case CategoriePerso.Cadre :
FBasePrime = 1000 ;
break;
case CategoriePerso.Maitrise :
FBasePrime = 500 ;
break;
case CategoriePerso.Agent :
FBasePrime = 200 ;
break;
}
}
///le constructeur de la classe employé sans mérite :
public Salarie ( int IDentifiant, string Nom, string Prenom,
CategoriePerso Categorie, string Insee ):
this( IDentifiant, Nom, Prenom, Categorie, Insee,0,0,0 )
{
}
protected double EvaluerPrimeCadreSup ( int coeffMerite )
{
return ( 100 + coeffMerite * 8 ) * FCoeffPrime * FBasePrime + FIndice * 7 ;
}
protected double EvaluerPrimeCadre ( int coeffMerite )
{
return ( 100 + coeffMerite * 6 ) * FCoeffPrime * FBasePrime + FIndice * 5 ;
}
protected double EvaluerPrimeMaitrise ( int coeffMerite )
{
return ( 100 + coeffMerite * 4 ) * FCoeffPrime * FBasePrime + FIndice * 3 ;
}
protected double EvaluerPrimeAgent ( int coeffMerite )
{
return ( 100 + coeffMerite * 2 ) * FCoeffPrime * FBasePrime + FIndice * 2 ;
}
/// propriété abstraite donnant le montant du salaire
/// (virtual automatiquement)
abstract public double MontantPaie
{
get ;
}
/// propriété identifiant le salarié dans l'entreprise :
public int IDentifiant
{
get
{
return FCodeEmploye ;
}
}
/// propriété nom du salarié :
public string Nom
{
get
{
return FNom ;
}
set
{
FNom = value ;
}
}
/// propriété nom du salarié :
public string Prenom
{
get
{
return FPrenom ;
}
set
{
FPrenom = value ;
}
}
/// propriété catégorie de personnel du salarié :
public CategoriePerso Categorie
{
get
{
return FCategorie ;
}
set
{
FCategorie = value ;
}
}
/// propriété n° de sécurité sociale du salarié :
public string Insee
{
get
{
return FInsee ;
}
set
{
FInsee = value ;
}
}
/// propriété de point de mérite du salarié :
public virtual int Merite
{
get
{
return FMerite ;
}
set
{
FMerite = value ;
}
}
/// propriété classement indiciaire dans la hiérarchie :
public int Indice_Hierarchique
{
get
{
return FIndice ;
}
set
{
FIndice = value ;
//--Maj de la date de détention du nouvel indice :
IndiceDepuis = DateTime.Now ;
}
}
/// propriété coefficient de la prime en %:
public double Coeff_Prime
{
get
{
return FCoeffPrime ;
}
set
{
FCoeffPrime = value ;
}
}
/// propriété valeur de la prime :
public double Prime
{
get
{
switch ( FCategorie )
{
case CategoriePerso.Cadre_Sup :
return EvaluerPrimeCadreSup ( FMerite );
case CategoriePerso.Cadre :
return EvaluerPrimeCadre ( FMerite );
case CategoriePerso.Maitrise :
return EvaluerPrimeMaitrise ( FMerite );
case CategoriePerso.Agent :
return EvaluerPrimeAgent ( FMerite );
default :
return EvaluerPrimeAgent ( 0 );
}
}
}
/// date à laquelle l'indice actuel a été obtenu :
public DateTime IndiceDepuis
{
get
{
return FIndiceDetenu ;
}
set
{
FIndiceDetenu = value ;
}
}
} // fin classe Salarie
/// <summary>
/// Classe du personnel mensualisé. Implémente la propriété abstraite
/// MontantPaie déclarée dans la classe de base (mère).
/// </summary>
class SalarieMensuel : Salarie
{
/// attributs du salaire annuel :
private double FPrime ;
private double FRemunerationTotal ;
///le constructeur de la classe (salarié au mérite) :
public SalarieMensuel ( int IDentifiant, string Nom, string Prenom,
CategoriePerso Categorie, string Insee, int Merite, int Indice,
double CoeffPrime, double RemunerationTotal ):
base ( IDentifiant, Nom, Prenom, Categorie, Insee, Merite, Indice, CoeffPrime )
{
FPrime = this .Prime ;
FRemunerationTotal = RemunerationTotal ;
}
/// implémentation de la propriété donnant le montant du salaire :
public override double MontantPaie
{
get
{
return ( FRemunerationTotal + this .Prime ) / 12 ;
}
}
/// propriété de point de mérite du salarié :
public override int Merite
{
get
{
return FMerite ;
}
set
{
FMerite = value ;
FPrime = this .Prime ;
}
}
} // fin classe SalarieMensuel
/// <summary>
/// Classe du personnel horaire. Implemente la propriété abstraite
/// MontantPaie déclarée dans la classe de base (mère).
/// </summary>
class SalarieHoraire : Salarie
{
/// attributs permettant le calcul du salaire :
private double FPrime ;
private double FTauxHoraire ;
private double FHeuresTravaillees ;
///le constructeur de la classe (salarié non au mérite):
public SalarieHoraire ( int IDentifiant, string Nom, string Prenom,
string Insee, double TauxHoraire ):
base ( IDentifiant, Nom, Prenom, CategoriePerso.Autre, Insee )
{
FTauxHoraire = TauxHoraire ;
FHeuresTravaillees = 0 ;
FPrime = 0 ;
}
/// nombre d'heures effectuées :
public double HeuresTravaillees
{
get
{
return FHeuresTravaillees ;
}
set
{
FHeuresTravaillees = value ;
}
}
/// implémentation de la propriété donnant le montant du salaire :
public override double MontantPaie
{
get
{
return FHeuresTravaillees * FTauxHoraire + FPrime ;
}
}
} // fin classe SalarieHoraire
class FichierDeSalaries
{
private string Fchemin ;
private ArrayList FListeEmployes ; // liste des nouveaux employés à entrer dans le fichier
private ArrayList indexCadreSup ; // Table d'index des cadres supérieurs du fichier
// méthode static affichant un objet Salarie à la console :
public static void AfficherUnSalarie ( Salarie Employe ) {
// pour l'instant un salarié mensualisé seulement
}
// constructeur de la classeFichierDeSalaries
public FichierDeSalaries ( string chemin, ArrayList Liste ) {
}
// méthode de création de la table d'index des cadre_sup :
public void CreerIndexCadreSup ( ) {
}
// méthode convertissant le champ string catégorie en la constante enum associée
private CategoriePerso strToCategorie ( string s ) {
}
// méthode renvoyant un objet SalarieMensuel de rang fixé dans le fichier
private Salarie EditerUnSalarie ( int rang ) {
SalarieMensuel perso ;
...........
perso = new SalarieMensuel ( IDentifiant, Nom, Prenom, Categorie, Insee,
Merite, Indice, CoeffPrime, RemunerationTotal );
...........
return perso ;
}
// méthode affichant sur la console à partir de la table d'index :
public void EditerFichierCadreSup ( )
{
...........
foreach( int ind in indexCadreSup )
{
AfficherUnSalarie ( EditerUnSalarie ( ind ) );
}
...........
}
// méthode affichant sur la console le fichier de tous les salariés :
public void EditerFichierSalaries ( ) {
}
// méthode créant et stockant des salariés dans le fichier :
public void StockerSalaries ( ArrayList ListeEmploy )
{
...........
// si le fichier n'existe pas => création du fichier sur disque :
fichierSortie = File.CreateText ( Fchemin );
fichierSortie.WriteLine ("Fichier des personnels");
fichierSortie.Close ();
...........
// ajout dans le fichier de toute la liste :
...........
foreach( Salarie s in ListeEmploy )
{
}
...........
}
} // fin classe FichierDeSalaries
Implémenter les classes avec le programme de test suivant :
class ClassUsesSalarie
{
/// <summary>
/// Le point d'entrée principal de l'application.
/// </summary>
static void InfoSalarie ( SalarieMensuel empl )
{
FichierDeSalaries.AfficherUnSalarie ( empl );
double coefPrimeLoc = empl.Coeff_Prime ;
int coefMeriteLoc = empl.Merite ;
//--impact variation du coef de prime
for( double i = 0.5 ; i < 1 ; i += 0.1 )
{
empl.Coeff_Prime = i ;
Console .WriteLine (" coeff prime : " + empl.Coeff_Prime );
Console .WriteLine (" montant prime annuelle : " + empl.Prime );
Console .WriteLine (" montant paie mensuelle: " + empl.MontantPaie );
}
Console .WriteLine (" -----------------------");
empl.Coeff_Prime = coefPrimeLoc ;
//--impact variation du coef de mérite
for( int i = 0 ; i < 10 ; i ++ )
{
empl.Merite = i ;
Console .WriteLine (" coeff mérite : " + empl.Merite );
Console .WriteLine (" montant prime annuelle : " + empl.Prime );
Console .WriteLine (" montant paie mensuelle: " + empl.MontantPaie );
}
empl.Merite = coefMeriteLoc ;
Console .WriteLine ("=======================================");
}
[STAThread]
static void Main ( string [] args )
{
SalarieMensuel Employe1 = new SalarieMensuel ( 123456, "Euton" , "Jeanne" ,
CategoriePerso.Cadre_Sup, "2780258123456" ,6,700,0.5,50000 );
SalarieMensuel Employe2 = new SalarieMensuel ( 123457, "Yonaize" , "Mah" ,
CategoriePerso.Cadre, "1821113896452" ,5,520,0.42,30000 );
SalarieMensuel Employe3 = new SalarieMensuel ( 123458, "Ziaire" , "Marie" ,
CategoriePerso.Maitrise, "2801037853781" ,2,678,0.6,20000 );
SalarieMensuel Employe4 = new SalarieMensuel ( 123459, "Louga" , "Belle" ,
CategoriePerso.Agent, "2790469483167" ,4,805,0.25,20000 );
ArrayList ListeSalaries = new ArrayList ();
ListeSalaries.Add ( Employe1 );
ListeSalaries.Add ( Employe2 );
ListeSalaries.Add ( Employe3 );
ListeSalaries.Add ( Employe4 );
foreach( SalarieMensuel s in ListeSalaries )
InfoSalarie ( s );
Console .WriteLine (">>> Promotion indice de " + Employe1.Nom + " dans 2 secondes.");
Thread.Sleep ( 2000 );
Employe1.Indice_Hierarchique = 710 ;
InfoSalarie ( Employe1 );
//-------------------------------------------//
FichierDeSalaries Fiches = new FichierDeSalaries ("fichierSalaries.txt" ,ListeSalaries );
Console .WriteLine (">>> Attente 3 s pour création de nouveaux salariés");
Thread.Sleep ( 3000 );
Employe1 = new SalarieMensuel ( 123460, "Miett" , "Hamas" ,
CategoriePerso.Cadre_Sup, "1750258123456" ,4,500,0.7,42000 );
Employe2 = new SalarieMensuel ( 123461, "Kong" , "King" ,
CategoriePerso.Cadre, "1640517896452" ,4,305,0.62,28000 );
Employe3 = new SalarieMensuel ( 123462, "Zaume" , "Philippo" ,
CategoriePerso.Maitrise, "1580237853781" ,2,245,0.8,15000 );
Employe4 = new SalarieMensuel ( 123463, "Micoton" , "Mylène" ,
CategoriePerso.Agent, "2850263483167" ,4,105,0.14,12000 );
ListeSalaries = new ArrayList ();
ListeSalaries.Add ( Employe1 );
ListeSalaries.Add ( Employe2 );
ListeSalaries.Add ( Employe3 );
ListeSalaries.Add ( Employe4 );
Fiches.StockerSalaries ( ListeSalaries );
Fiches.EditerFichierSalaries ();
Fiches.CreerIndexCadreSup ();
Fiches.EditerFichierCadreSup ();
System .Console.ReadLine ();
}
}
}
Exemple de résultats obtenus avec le programme de test précédent :
fichierSalaries.txt :
Fichier des personnels
123456
Euton
Jeanne
*Cadre_Sup
2780258123456
6
710
15/02/2004 19:52:38
0,5
152970
16914,1666666667
123457
Yonaize
Mah
*Cadre
1821113896452
5
520
15/02/2004 19:52:36
0,42
57200
7266,66666666667
123458
Ziaire
Marie
*Maitrise
2801037853781
2
678
15/02/2004 19:52:36
0,6
34434
4536,16666666667
123459
Louga
Belle
*Agent
2790469483167
4
805
15/02/2004 19:52:36
0,25
7010
2250,83333333333
123460
Miett
Hamas
*Cadre_Sup
1750258123456
4
500
15/02/2004 19:52:41
0,7
188300
19191,6666666667
123461
Kong
King
*Cadre
1640517896452
4
305
15/02/2004 19:52:41
0,62
78405
8867,08333333333
123462
Zaume
Philippo
*Maitrise
1580237853781
2
245
15/02/2004 19:52:41
0,8
43935
4911,25
123463
Micoton
Mylène
*Agent
2850263483167
4
105
15/02/2004 19:52:41
0,14
3234
1269,5
Résultats console :
Employé n°123456: Euton / Jeanne
n° SS : 2780258123456
catégorie : Cadre_Sup
indice hiérarchique : 700 , détenu depuis : 15/02/2004 19:52:36
coeff mérite : 6
coeff prime : 0,5
montant prime annuelle : 152900
montant paie mensuelle: 16908,3333333333
coeff prime : 0,5
montant prime annuelle : 152900
montant paie mensuelle: 16908,3333333333
coeff prime : 0,6
montant prime annuelle : 182500
montant paie mensuelle: 19375
coeff prime : 0,7
montant prime annuelle : 212100
montant paie mensuelle: 21841,6666666667
coeff prime : 0,8
montant prime annuelle : 241700
montant paie mensuelle: 24308,3333333333
coeff prime : 0,9
montant prime annuelle : 271300
montant paie mensuelle: 26775
coeff prime : 1
montant prime annuelle : 300900
montant paie mensuelle: 29241,6666666667
-----------------------
coeff mérite : 0
montant prime annuelle : 104900
montant paie mensuelle: 12908,3333333333
coeff mérite : 1
montant prime annuelle : 112900
montant paie mensuelle: 13575
coeff mérite : 2
montant prime annuelle : 120900
montant paie mensuelle: 14241,6666666667
coeff mérite : 3
montant prime annuelle : 128900
montant paie mensuelle: 14908,3333333333
coeff mérite : 4
montant prime annuelle : 136900
montant paie mensuelle: 15575
coeff mérite : 5
montant prime annuelle : 144900
montant paie mensuelle: 16241,6666666667
coeff mérite : 6
montant prime annuelle : 152900
montant paie mensuelle: 16908,3333333333
coeff mérite : 7
montant prime annuelle : 160900
montant paie mensuelle: 17575
coeff mérite : 8
montant prime annuelle : 168900
montant paie mensuelle: 18241,6666666667
coeff mérite : 9
montant prime annuelle : 176900
montant paie mensuelle: 18908,3333333333
=======================================
Employé n°123457: Yonaize / Mah
n° SS : 1821113896452
catégorie : Cadre
indice hiérarchique : 520 , détenu depuis : 15/02/2004 19:52:36
coeff mérite : 5
coeff prime : 0,42
montant prime annuelle : 57200
montant paie mensuelle: 7266,66666666667
coeff prime : 0,5
montant prime annuelle : 67600
montant paie mensuelle: 8133,33333333333
coeff prime : 0,6
montant prime annuelle : 80600
montant paie mensuelle: 9216,66666666667
coeff prime : 0,7
montant prime annuelle : 93600
montant paie mensuelle: 10300
coeff prime : 0,8
montant prime annuelle : 106600
montant paie mensuelle: 11383,3333333333
coeff prime : 0,9
montant prime annuelle : 119600
montant paie mensuelle: 12466,6666666667
coeff prime : 1
montant prime annuelle : 132600
montant paie mensuelle: 13550
-----------------------
coeff mérite : 0
montant prime annuelle : 44600
montant paie mensuelle: 6216,66666666667
coeff mérite : 1
montant prime annuelle : 47120
montant paie mensuelle: 6426,66666666667
coeff mérite : 2
montant prime annuelle : 49640
montant paie mensuelle: 6636,66666666667
coeff mérite : 3
montant prime annuelle : 52160
montant paie mensuelle: 6846,66666666667
coeff mérite : 4
montant prime annuelle : 54680
montant paie mensuelle: 7056,66666666667
coeff mérite : 5
montant prime annuelle : 57200
montant paie mensuelle: 7266,66666666667
coeff mérite : 6
montant prime annuelle : 59720
montant paie mensuelle: 7476,66666666667
coeff mérite : 7
montant prime annuelle : 62240
montant paie mensuelle: 7686,66666666667
coeff mérite : 8
montant prime annuelle : 64760
montant paie mensuelle: 7896,66666666667
coeff mérite : 9
montant prime annuelle : 67280
montant paie mensuelle: 8106,66666666667
=======================================
Employé n°123458: Ziaire / Marie
n° SS : 2801037853781
catégorie : Maitrise
indice hiérarchique : 678 , détenu depuis : 15/02/2004 19:52:36
coeff mérite : 2
coeff prime : 0,6
montant prime annuelle : 34434
montant paie mensuelle: 4536,16666666667
coeff prime : 0,5
montant prime annuelle : 29034
montant paie mensuelle: 4086,16666666667
coeff prime : 0,6
montant prime annuelle : 34434
montant paie mensuelle: 4536,16666666667
coeff prime : 0,7
montant prime annuelle : 39834
montant paie mensuelle: 4986,16666666667
coeff prime : 0,8
montant prime annuelle : 45234
montant paie mensuelle: 5436,16666666667
coeff prime : 0,9
montant prime annuelle : 50634
montant paie mensuelle: 5886,16666666667
coeff prime : 1
montant prime annuelle : 56034
montant paie mensuelle: 6336,16666666667
-----------------------
coeff mérite : 0
montant prime annuelle : 32034
montant paie mensuelle: 4336,16666666667
coeff mérite : 1
montant prime annuelle : 33234
montant paie mensuelle: 4436,16666666667
coeff mérite : 2
montant prime annuelle : 34434
montant paie mensuelle: 4536,16666666667
coeff mérite : 3
montant prime annuelle : 35634
montant paie mensuelle: 4636,16666666667
coeff mérite : 4
montant prime annuelle : 36834
montant paie mensuelle: 4736,16666666667
coeff mérite : 5
montant prime annuelle : 38034
montant paie mensuelle: 4836,16666666667
coeff mérite : 6
montant prime annuelle : 39234
montant paie mensuelle: 4936,16666666667
coeff mérite : 7
montant prime annuelle : 40434
montant paie mensuelle: 5036,16666666667
coeff mérite : 8
montant prime annuelle : 41634
montant paie mensuelle: 5136,16666666667
coeff mérite : 9
montant prime annuelle : 42834
montant paie mensuelle: 5236,16666666667
=======================================
Employé n°123459: Louga / Belle
n° SS : 2790469483167
catégorie : Agent
indice hiérarchique : 805 , détenu depuis : 15/02/2004 19:52:36
coeff mérite : 4
coeff prime : 0,25
montant prime annuelle : 7010
montant paie mensuelle: 2250,83333333333
coeff prime : 0,5
montant prime annuelle : 12410
montant paie mensuelle: 2700,83333333333
coeff prime : 0,6
montant prime annuelle : 14570
montant paie mensuelle: 2880,83333333333
coeff prime : 0,7
montant prime annuelle : 16730
montant paie mensuelle: 3060,83333333333
coeff prime : 0,8
montant prime annuelle : 18890
montant paie mensuelle: 3240,83333333333
coeff prime : 0,9
montant prime annuelle : 21050
montant paie mensuelle: 3420,83333333333
coeff prime : 1
montant prime annuelle : 23210
montant paie mensuelle: 3600,83333333333
-----------------------
coeff mérite : 0
montant prime annuelle : 6610
montant paie mensuelle: 2217,5
coeff mérite : 1
montant prime annuelle : 6710
montant paie mensuelle: 2225,83333333333
coeff mérite : 2
montant prime annuelle : 6810
montant paie mensuelle: 2234,16666666667
coeff mérite : 3
montant prime annuelle : 6910
montant paie mensuelle: 2242,5
coeff mérite : 4
montant prime annuelle : 7010
montant paie mensuelle: 2250,83333333333
coeff mérite : 5
montant prime annuelle : 7110
montant paie mensuelle: 2259,16666666667
coeff mérite : 6
montant prime annuelle : 7210
montant paie mensuelle: 2267,5
coeff mérite : 7
montant prime annuelle : 7310
montant paie mensuelle: 2275,83333333333
coeff mérite : 8
montant prime annuelle : 7410
montant paie mensuelle: 2284,16666666667
coeff mérite : 9
montant prime annuelle : 7510
montant paie mensuelle: 2292,5
=======================================
>>> Promotion indice de Euton dans 2 secondes.
Employé n°123456: Euton / Jeanne
n° SS : 2780258123456
catégorie : Cadre_Sup
indice hiérarchique : 710 , détenu depuis : 15/02/2004 19:52:38
coeff mérite : 6
coeff prime : 0,5
montant prime annuelle : 152970
montant paie mensuelle: 16914,1666666667
coeff prime : 0,5
montant prime annuelle : 152970
montant paie mensuelle: 16914,1666666667
coeff prime : 0,6
montant prime annuelle : 182570
montant paie mensuelle: 19380,8333333333
coeff prime : 0,7
montant prime annuelle : 212170
montant paie mensuelle: 21847,5
coeff prime : 0,8
montant prime annuelle : 241770
montant paie mensuelle: 24314,1666666667
coeff prime : 0,9
montant prime annuelle : 271370
montant paie mensuelle: 26780,8333333333
coeff prime : 1
montant prime annuelle : 300970
montant paie mensuelle: 29247,5
-----------------------
coeff mérite : 0
montant prime annuelle : 104970
montant paie mensuelle: 12914,1666666667
coeff mérite : 1
montant prime annuelle : 112970
montant paie mensuelle: 13580,8333333333
coeff mérite : 2
montant prime annuelle : 120970
montant paie mensuelle: 14247,5
coeff mérite : 3
montant prime annuelle : 128970
montant paie mensuelle: 14914,1666666667
coeff mérite : 4
montant prime annuelle : 136970
montant paie mensuelle: 15580,8333333333
coeff mérite : 5
montant prime annuelle : 144970
montant paie mensuelle: 16247,5
coeff mérite : 6
montant prime annuelle : 152970
montant paie mensuelle: 16914,1666666667
coeff mérite : 7
montant prime annuelle : 160970
montant paie mensuelle: 17580,8333333333
coeff mérite : 8
montant prime annuelle : 168970
montant paie mensuelle: 18247,5
coeff mérite : 9
montant prime annuelle : 176970
montant paie mensuelle: 18914,1666666667
=======================================
>>> Attente 3 s pour création de nouveaux salariés
Fichier des personnels
123456
Euton
Jeanne
*Cadre_Sup
2780258123456
6
710
15/02/2004 19:52:38
0,5
152970
16914,1666666667
123457
Yonaize
Mah
*Cadre
1821113896452
5
520
15/02/2004 19:52:36
0,42
57200
7266,66666666667
123458
Ziaire
Marie
*Maitrise
2801037853781
2
678
15/02/2004 19:52:36
0,6
34434
4536,16666666667
123459
Louga
Belle
*Agent
2790469483167
4
805
15/02/2004 19:52:36
0,25
7010
2250,83333333333
123460
Miett
Hamas
*Cadre_Sup
1750258123456
4
500
15/02/2004 19:52:41
0,7
188300
19191,6666666667
123461
Kong
King
*Cadre
1640517896452
4
305
15/02/2004 19:52:41
0,62
78405
8867,08333333333
123462
Zaume
Philippo
*Maitrise
1580237853781
2
245
15/02/2004 19:52:41
0,8
43935
4911,25
123463
Micoton
Mylène
*Agent
2850263483167
4
105
15/02/2004 19:52:41
0,14
3234
1269,5
++> *Cadre_Sup : 5
++> *Cadre_Sup : 49
Employé n°123456: Euton / Jeanne
n° SS : 2780258123456
catégorie : Cadre_Sup
indice hiérarchique : 710 , détenu depuis : 15/02/2004 19:52:38
coeff mérite : 6
coeff prime : 0
montant prime annuelle : 4970
montant paie mensuelle: 414,208333333333
Employé n°123460: Miett / Hamas
n° SS : 1750258123456
catégorie : Cadre_Sup
indice hiérarchique : 500 , détenu depuis : 15/02/2004 19:52:41
coeff mérite : 4
coeff prime : 0
montant prime annuelle : 3500
montant paie mensuelle: 291,725