import java.io.*;
import java.util.Scanner;
import java.util.Locale;

/**
 * Fonctions de gestion de fichier texte.<br>
 * <br>
 * Un fichier texte contient des informations codees sous forme texte.<br>
 * Un tel fichier pourra etre exploite depuis un editeur texte car les informations qui y sont contenues sont directement accessibles.<br>
 * <br>
 * Creer un fichier texte pour y stocker de l'information necessite de creer le fichier, y ecrire les informations a sauvegarder et fermer le fichier.<br>
 * La creation d'un fichier necessite de donner le nom qu'il portera sur le support de sauvegarde ou il sera ecrit.<br>
 * L'exemple suivant illustre la creation d'un fichier ou sont sauvegardees les valeurs entiere 12 et reelle 2.897:<br>
 * <font style="size: 12px;font-family: Courier, monospace"><b>
 * &nbsp;  Fichier f = new Fichier();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;                  // Declaration de la variable support du fichier<br>
 * &nbsp;  if ( Fichier.ouvrir(f,"Test.txt","c") ) {&nbsp;   // Si l'ouverture du fichier en creation avec le nom Test.txt a ete reussie<br>
 * &nbsp;&nbsp;&nbsp;    Fichier.afficherln(f,12);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;                 // Ecriture dans le fichier de la valeur entiere 12<br>
 * &nbsp;&nbsp;&nbsp;    Fichier.afficherln(f,2.897);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;              // Ecriture dans le fichier de la valeur reelle 2.897<br>
 * &nbsp;&nbsp;&nbsp;    Fichier.fermer(f);&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;                      // Fermeture du fichier</b></font><br>
 * <br>
 * Pour que les valeurs sauvegardees soient discriminables les unes des autres, il est necessaire qu'elles soient separees par un delimiteur. Celui-ci peut etre le caractere espace ou un saut de ligne comme dans l'exemple ci-dessus.<br>
 * <br>
 * L'exemple suivant illustre la lecture du fichier texte cree par l'exemple precedent:<br>
 * <font style="size: 12px;font-family: Courier, monospace;"><b>
 * &nbsp;  int v1;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;                  // Declaration de la variable int v1<br>
 * &nbsp;  double v2;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;                  // Declaration de la variable double v2<br>
 * &nbsp;  Fichier f = new Fichier();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;                  // Declaration de la variable support du fichier<br>
 * &nbsp;  if ( Fichier.ouvrir(f,"Test.txt","r") ) {&nbsp;   // Si l'ouverture du fichier en lecture avec le nom Test.txt a ete reussie<br>
 * &nbsp;&nbsp;&nbsp;    v1 = Fichier.lireInt(f);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;                 // Lecture dans le fichier d'une valeur de type int<br>
 * &nbsp;&nbsp;&nbsp;    v2 = Fichier.lireDouble(f);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;              // Lecture dans le fichier d'une valeur de type double<br>
 * &nbsp;&nbsp;&nbsp;    Fichier.fermer(f);&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;                      // Fermeture du fichier</b></font><br>
 * <br>
 * Les donnees d'un fichier ne peuvent etre lues que dans l'ordre avec lequel elles ont ete ecrites. Il est obligatoire que chaque instruction de lecture soit compatible avec la donnee a lire.<br>
 * Consequence: Un lireInt sur une donnee non numerique entiere entraine une erreur d'execution.<br>
 * <br>
 * Remarque: Plusieurs fichiers peuvent etre ouverts simultanement avec des modes d'exploitation differents. Il est necessaire que chacun d'eux ait une variable support individuelle.
 */

public class Fichier {

  private
    String filename;
    Scanner in = null;
    PrintWriter out = null;

  /**
    * Ouverture d'un fichier.
    *
    * @param f Le Fichier à ouvrir.
    * @param filename Le nom du Fichier à ouvrir.
    * @param mode Le mode d'ouverture du fichier ("r" pour lecture, "c" pour création puis écriture, "w" pour écriture en queue).
    * @return Le booleen indiquant si l'ouverture a abouti.
    */
  public static boolean ouvrir(Fichier f,String filename,String mode) {
    f.filename = new String(filename);
    if ( mode == "r" ) {
      try {
        f.in = new Scanner(new FileInputStream(filename));
        f.in.useLocale(Locale.US); }
      catch (Exception e) {
        System.out.println("Erreur");
        return(false); }
      return(f.in != null); }
    if ( mode == "w" ) {
      try {
        f.out = new PrintWriter(new OutputStreamWriter(new FileOutputStream(new File(filename),true))); }
      catch (Exception e) {
        System.out.println("Erreur");
        return(false); }
      return(f.out != null); }
    if ( mode == "c" ) {
      try {
        { File file = new File(filename);
          file.delete(); }
        f.out = new PrintWriter(new OutputStreamWriter(new FileOutputStream(new File(filename),true))); }
      catch (Exception e) {
        System.out.println("Erreur");
        return(false); }
      return(f.out != null); }
    return(false);
  }

  /**
    * Fermeture d'un fichier.
    *
    * @param f Le Fichier à fermer.
    */
  public static void fermer(Fichier f) {
    try {
      if ( f.in != null )
        f.in.close(); }
    catch (Exception e) { }
    try {
      if ( f.out != null )
        f.out.close(); }
    catch (Exception e) { }
  }

  /**
    * Test de l'existence d'une valeur encore à lire dans un fichier.
    *
    * @param f Le Fichier dans lequel réaliser la lecture.
    * @return Le booleen indiquant si une valeur reste à lire (true si oui, false si non).
    */
  public static boolean estFini(Fichier f) {
    try {
      if ( f.in != null )
        return(!f.in.hasNext()); }
    catch (Exception e) { }
    return(true);
  }
  
  /**
    * Ecriture dans un fichier.<p>
    * Indication entre parenthèses de la liste des 0, 1 ou plusieurs parametres à écrire:<br>
    * - variables,<br>
    * - constantes,<br>
    * - expressions,<br>
    * - ...
    *
    * @param f Le Fichier dans lequel réaliser l'écriture.
    * @param s La liste des parametres a ecrire dans le fichier.
    */
	public static void afficher(Fichier f,Object... s) {
		for (Object o : s) {
			f.out.print(o.toString()); }
	}

  /**
    * Ecriture dans un fichier suivie d'un saut de ligne.<p>
    * Indication entre parenthèses de la liste des 0, 1 ou plusieurs parametres à écrire:<br>
    * - variables,<br>
    * - constantes,<br>
    * - expressions,<br>
    * - ...
    *
    * @param f Le Fichier dans lequel réaliser l'écriture.
    * @param s La liste des parametres a ecrire dans le fichier.
    */
	public static void afficherln(Fichier f,Object... s) {
		for (Object o : s) {
			f.out.print(o.toString()); }
		f.out.println();
	}

  /**
    * Saut de ligne dans un fichier.
    *
    * @param f Le Fichier dans lequel réaliser l'écriture.
    */
	public static void sautDeLigne(Fichier f) {
		f.out.println();
	}

  /**
    * Lecture dans un fichier d'une valeur de type byte (octet).
    *
    * @param f Le Fichier dans lequel réaliser la lecture.
    * @return Le byte lu dans le fichier.
    */
	public static byte lireByte(Fichier f){
		byte b = 0x00;
    if ( f.in != null ) {
      try {
        b = f.in.nextByte(); }
      catch(Exception e) { } }
		return b;
	}

  /**
    * Lecture dans un fichier d'une valeur de type short (entier sur 2 octets).
    *
    * @param f Le Fichier dans lequel réaliser la lecture.
    * @return Le short lu dans le fichier.
    */
	public static short lireShort(Fichier f){
		short s = 0;
    if ( f.in != null ) {
      try {
        s = f.in.nextShort(); }
      catch(Exception e) { } }
		return s;
	}

  /**
    * Lecture dans un fichier d'une valeur de type int (entier sur 4 octets).
    *
    * @param f Le Fichier dans lequel réaliser la lecture.
    * @return Le int lu dans le fichier.
    */
	public static int lireInt(Fichier f){
		int i = 0;
    if ( f.in != null ) {
      try {
        i = f.in.nextInt(); }
      catch(Exception e) { } }
		return i;
	}

  /**
    * Lecture dans un fichier d'une valeur de type long (entier sur 8 octets).
    *
    * @param f Le Fichier dans lequel réaliser la lecture.
    * @return Le long lu dans le fichier.
    */
	public static long lireLong(Fichier f){
		long l = 0L;
    if ( f.in != null ) {
      try {
        l = f.in.nextLong(); }
      catch(Exception e) { } }
		return l;
	}

  /**
    * Lecture dans un fichier d'une valeur de type double (réel double précision (sur 8 octets)).
    *
    * @param f Le Fichier dans lequel réaliser la lecture.
    * @return Le double lu dans le fichier.
    */
	public static double lireDouble(Fichier f){
		double d = 0.0;
    if ( f.in != null ) {
      try {
        d = f.in.nextDouble(); }
      catch(Exception e) { } }
		return d;
	}

  /**
    * Lecture dans un fichier d'une valeur de type float (réel simple précision (sur 4 octets)).
    *
    * @param f Le Fichier dans lequel réaliser la lecture.
    * @return Le float lu dans le fichier.
    */
	public static float lireFloat(Fichier f){
		float fv = 0.0F;
    if ( f.in != null ) {
      try {
        fv = f.in.nextFloat(); }
      catch(Exception e) { } }
		return fv;
	}

  /**
    * Lecture dans un fichier d'une valeur de type booleen.
    *
    * @param f Le Fichier dans lequel réaliser la lecture.
    * @return Le booleen lu dans le fichier.
    */
	public static boolean lireBoolean(Fichier f){
		boolean b = true;
    if ( f.in != null ) {
      try {
        b = f.in.nextBoolean(); }
      catch(Exception e) { } }
		return b;
	}

  /**
    * Lecture dans un fichier d'une valeur de type chaine de caractères (jusqu'au bout de la ligne en cours).
    *
    * @param f Le Fichier dans lequel réaliser la lecture.
    * @return La String lue dans le fichier.
    */
	public static String lireString(Fichier f){
		String s = "";
    if ( f.in != null ) {
      boolean lu;
      do {
        try {
          s = f.in.nextLine();
          lu = true; }
        catch(Exception e) {
          lu = false; } }
      while ( !lu || ( s.equals("") ) ); }
		return s;
	}

  /**
    * Lecture dans un fichier d'une valeur de type chaine de caractères (un mot).
    *
    * @param f Le Fichier dans lequel réaliser la lecture.
    * @return La String lue dans le fichier.
    */
	public static String lireMot(Fichier f){
		String s = "";
    if ( f.in != null ) {
      try {
        s = f.in.next(); }
      catch(Exception e) { } }
		return s;
	}  

  /**
    * Lecture dans un fichier d'une valeur de type caractère.
    *
    * @param f Le Fichier dans lequel réaliser la lecture.
    * @return Le caractere lu dans le fichier.
    */
	public static char lireChar(Fichier f){
		String s = "";
    if ( f.in != null ) {
      try {
        s = f.in.next(); }
      catch(Exception e) { } }
		return s.toCharArray()[0];
	}  
}