4.1. Données simples et fichiers en C#



Plan général:   ...........revenir au plan général

 
1. Les manipulations disque de fichiers et de répertoires

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#
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

3. Exercice de fichier de salariés avec une IHM




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.
 

 
 
 

2.1 Les flux avec C#

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.


2.2 Les flux et les fichiers de caractères avec C#

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" ))    {
       // 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
 }
                Console.WriteLine("Contenu du fichier essai.txt déjà présent :");
                 // 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 :
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
            }
Code source C# lisant le contenu du fichier essai.txt :

                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 += 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 ++ )
   {
    
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