View on GitHub

lp4-2019

Découvertes des entrées sorties

Les entrées sorties sont vues par Java comme des flux d’octets ou de caractères. Le package java.io fournit les classes chargées des opérations de lecture et écriture. Les lectures et écritures sont indépendantes des supports. On construira un flux en utilisant une ou plusieurs classes.

Remarques :

Par exemple :

En java, il existe 2 types de flux :

Exemple d’InputStream : System.in (entrée standard = le clavier) Les classes dont le nom contient un nom de ressource ( File, ByteArray, String, … ) permettent de faire un lien avec ces resources.

Exemples :

Les classes dont le nom contient stream et er servent à la conversion de flux d’octets en flux de caractères.

InputStreamReader lit des bytes pour les transformer en caractères tandis que OutputStreamWriter écrit des caractères dans un flux en sortie, en les transformant en bytes (avec encodage).

Il existe des classes qui ajoutent des fonctionalités à des flux existants.

Pour la gestion des tampons mémoires, nous avons les classes :

Pour l’utilisation de méthodes de lecture / écriture pour des types internes, nous avons :

Pour l’écriture et la lecture d’objets, nous avons :

Remarques : DataInputStream et DataOutputStream permettent une representation binaire portable (indépendante de la plateforme) de types primitives java. ObjectOutputStream et ObjectInputStream servent à la sérialisation / désérialisation d’objets ou de tableaux. Elles fournissent réciproquement les méthodes writeObject() et readObject().

Les méthodes du flux InputStream

InputStream est une classe abstraite, super-classe de tous les flux d’octets en entrée. Cette classe apporte les méthodes de base pour les sous-classes (exemple : read() ).

Méthodes dédiées à la lecture

octet par octet :

par tableau d’octets :

Les opérations de lecture sont blocantes.

Autres méthodes :

Les méthodes du flux OutputStream :

Méthodes dédiées à l’écriture :

octet par octet :

Autres méthodes :

Fichier vu comme un flux d’octets :

Les constructeurs reçoivent le nom du fichier :

Pour lire :

Pour écrire :

Ajout en fin de fichier :

Exemple de code java avec flux d’octets :

FileInputStream fis = null ; FileOutputStream fos = null ;
try
{
fis = new FileInputStream( "fichier.dat" ) ;
fos = new FileOutputStream( "copie.dat" ) ;
int octet = 0 ;
while( true )
{
octet = fis.read() ;
if( octet == -1 ) break ;
fos.write( octet ) ;
}
fos.close(); fis.close();
}
catch( FileNotFoundException fnfe )
{
System.out.println( fnfe.getMessage() ) ;
}
catch( IOException ioe ) {
}

Flux de caractères avec Reader

Méthodes de lecture :

Autres méthodes :

Flux de caractères avec Writer :

Méthodes d’écriture

Par tableau de caractères

- void write( char [] tableau ) throws IOException;
- void write( char [] tableau, int offset, int nb ) throws IOException;

Autres méthodes :

Les classes de conversion :

Conversion de flux d’octets en flux de caractères.

Avec spécification du code page à utiliser pour la conversion :

Conversion de flux de caractères en flux d’octets :

Voici un exemple de quelques codepage :

Les classes filtres :

Ajout de tampon mémoire et de méthode readLine :

Ajout de méthodes print() et println() :

Les méthodes de PrintWriter ne lancent pas d’exceptions !

Exemple de code avec un flux de caractères :

BufferedReader br = null ;
PrintWriter pw = null ;
try
{
InputStreamReader rd = new InputStreamReader( System.in );
br = new BufferedReader( rd ) ;
FileWriter fw = new FileWriter( "log.txt" , true ) ;
pw = new PrintWriter( fw ) ;
String s = null ;
while(( s = br.readLine() ) != null )
{
System.out.println( s ) ;
pw.println( s ) ;
}
pw.close( ); br.close( ) ;
}
catch( IOException ioe )
{
}

Voici un exemple de code d’écriture et de lecture d’un flux d’octets :

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

class TestEntreesSorties

{
	public static void main (String[] args)

	{

		// lecture / écriture d'un flux d'octets
		// déclaration de 2 types d'objets
		FileInputStream fis = null;
		FileOutputStream fos = null;
		FileOutputStream fosf = null;

		// bloc try

		try
		{
			// création des objets de type File :
			fis = new FileInputStream("toto.txt");
			// flux en lecture
			fos = new FileOutputStream("titi.txt");
			// flux en écriture
			fosf = new FileOutputStream("bobo.txt",true);
			// écriture mode ajout

			int octet = 0;

			while (true)
			{
				octet = fis.read();
 			// lecture du flux d'octets dans toto.txt
				if (octet == -1) break;	// si fin de fichier on sort
				fos.write(octet);		// écriture de l'octet dans titi.txt
				fosf.write(octet);
 			// écriture de l'octet dans bobo.txt en mode ajout
			}

			fos.close();	// on ferme le flux d'octets en écriture
			fosf.close();	// idem
			fis.close();	// idem pour la lecture

		}
		// on attrape l'exception si un fichier n'est pas trouvé !
		catch (FileNotFoundException fnfe)
		{
			System.out.println(fnfe.getMessage());
		}
		catch (IOException ioe)
		{
			System.out.println(ioe.getMessage());
		}
		finally
		{

			System.out.println("Opération terminée");

			// il ne vous reste plus qu'à aller voir le contenu des
			// fichiers titi, toto et bobo dans votre répertoire.
		}


	}
}

Classe File

La classe File fournit un certain nombre de services se rapportant aux fichiers et aux répertoires.

Constructeurs :

nom représente un nom de fichier ou de répertoire. parent le nom du répertoire en relation avec le fichier.

Les informations sur un fichier :

Pour les répertoires :

Exemple de traitement d’une exception générée par un fichier non trouvé :

// importation des paquetages nécessaires :
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

class FichierInexistant
{
	private String monFichier="titi.txt";

/*
	public void setMonFichier(String f)
	{
		monFichier=f;
	}
*/
	// constructeur
	public FichierInexistant()
	{

	try

	{
		FileInputStream fis = new FileInputStream(monFichier);
		int longueurFichier = fis.available();

		// lecture du fichier
		byte[] readBuffer = new byte[longueurFichier];
		fis.read(readBuffer);

		// fermeture de fichier
		fis.close();
	}

	/* ici, le catch permet d'attraper une erreur (exception)
	   en cas de "fichier non trouvé". Les exceptions sont des
	   classes comme les autres, elles permettent d'instancier
	   à partir de la classe Exception ou des classes dérivées.
	*/
	catch (FileNotFoundException e)
	{
		System.out.println("le Fichier "+monFichier+ " est introuvable !");
		// on pourrait proposer une nouvelle saisie du nom du fichier et
		// rappeler une méthode ...
	}

	catch (IOException e)
	{
		System.out.println("Erreur de lecture du fichier !");
	}

}

}

public class TestDesExceptionsIO

{
	public static void main (String[] args)
	{

		FichierInexistant fi = new FichierInexistant();

	}
}	// fin de la classe TestDesExceptionsIO

Exemple de code d’écriture de caractères (phrase) et de lecture d’octets dans un fichier :

import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;

public class TestFlux
{
	public static void main(String argv[])
	{
		// Ecriture dans un fichier :
		try
		{
// déclarer et créer un flux fw de type FileWriter lié à la ressource fichier "sortie.log".
			FileWriter fw = new FileWriter("sortie.log");
// Utilisez le flux fw pour écrire un texte dans le fichier "sortie.log".
			fw.write("Bonjour, cette phrase a bien été enregistrée dans un fichier");
			//Fermez le flux.
			fw.close();
		}
		catch (IOException e)
		{
			e.printStackTrace();
		}

		// lecture de ce que vous avez écrit et affichage dans la console :
		try
		{
			StringBuffer phrases = new StringBuffer();
			FileInputStream fis = new FileInputStream("sortie.log");
			int octet=0;
			while (true)
			{
				octet = fis.read();
				if (octet == -1) break;	// fin de fichier, on sort
		//ici, vous constater un casting en type char pour caractère
				phrases.append((char)octet);

			}
		// on ferme le flux :
			fis.close();
			System.out.println(phrases.toString());
		}
		catch (IOException e)
		{
			e.printStackTrace();
		}


	}
}

Autre exemple de saisie en console et sauvegarde d’un message dans un fichier :

import java.io.BufferedReader;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
//La classe suivante permet de tester les flux standards
public class TestFluxStandards
{
	public static void main (String args[])
	{
		// Gérer l'exception IOException.		    	
		try
		{
			String message="";
// Récupérez le flux d'entrée in et ajouter un flux avec tampon (InputStreamReader) de données pour pouvoir lire une ligne entière.
			BufferedReader entree =new BufferedReader(new InputStreamReader(System.in));
			// Créer flux de sortie vers un fichier "log.txt"
			PrintWriter ecrire= new PrintWriter(new FileOutputStream("log.txt"));

		//  Tant que le message de la console est différent de "q",
		// Ecrire le message dans le fichier log.txt et à la console.
			message = "---> Entrer votre message svp (q pour quitter): ";
			System.out.println(message);
			message = entree.readLine ();
			while (!message.equalsIgnoreCase("q"))
			{
				System.out.println("votre message : \" " + message + " \"\n\n");
				ecrire.println(message);
				message = "---> Entrer votre message svp (q pour quitter): ";
				System.out.println(message);
				// utilisation du flux d'entrée
				message = entree.readLine ();
			}        
			// Fermer les flux.
			ecrire.close();
			entree.close();
		}
		catch (IOException e)
		{
			e.printStackTrace();
		}

	}
}

Exemple d’écriture et de lecture des objets de type Chat (animal) dans un fichier :

package enregistrerDesObjetsChats;
import java.io.Serializable;
/**
 * Projet 	:	TP-exemple
 * Classe	:	Chat.java
 * @author 	:	Philippe Bouget
 * Date	:	03/10/2019
 */
public class Chat implements Serializable {

	private String petitNom;
	private int age;

	public Chat(String p, int a)
	{
		this.petitNom=p;
		this.age=a;
	}

	/**
	 * @return le petitNom
	 */
	public String getPetitNom() {
		return petitNom;
	}

	/**
	 * @param petitNom le petitNom à initialiser
	 */
	public void setPetitNom(String petitNom) {
		this.petitNom = petitNom;
	}

	/**
	 * @return le age
	 */
	public int getAge() {
		return age;
	}

	/**
	 * @param age le age à initialiser
	 */
	public void setAge(int age) {
		this.age = age;
	}
	public String toString()
	{
		return "Chat : :"+petitNom+" "+age+" ans";
	}
	public void afficher()
	{
		System.out.println("Chat : :"+petitNom+" "+age+" ans");
	}
}

Comme vous pouvez le constater dans la déclaration de la classe Chat, on implémente l’interface Serializable de la manière suivante :

Cela suffit pour rendre l’écriture, la transmission via un réseau et la lecture d’objets possible.

Exemple d’écriture des objets :

package enregistrerDesObjetsChats;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
/**============================================
	Ecriture d'objet dans un Fichier texte
	Gestion des flux entrée / sortie
	Auteur  		: Philippe Bouget
	Année			  : 2019
	Nom Programme	: EcrireObjet.java
==============================================
 */
public class EcrireObjet

{
	public static void main (String args[])
	{
		// on créer des références à des objets Chat
		Chat minou = new Chat("Youpi",3);
		Chat poupou = new Chat("Poupou",4);
		Chat propret = new Chat("Propret",7);
		Chat pounette = new Chat("Pounette",8);
		try
		{
FileOutputStream fichierDObjets = new FileOutputStream("ChatObj.txt");
ObjectOutputStream fluxDObjets = new ObjectOutputStream(fichierDObjets);

			minou.afficher();
			fluxDObjets.writeObject(minou);

			poupou.afficher();
			fluxDObjets.writeObject(poupou);

			propret.afficher();
			fluxDObjets.writeObject(propret);

			pounette.afficher();
			fluxDObjets.writeObject(pounette);
			// on vide le tampon
			fluxDObjets.flush();
			// on ferme la fichier
			fluxDObjets.close();
			fichierDObjets.close();
			System.out.println("Fin de la copie du fichier");		
		}
		catch (IOException e) {e.getMessage();}

	}
}

Pour l’écriture des objets on déclare un objet du type ObjectOutputStream qui nous permet de faire appel à la méthode writeObject() pour sauvegarder un objet. Il faut bien entendu effectuer un flush() puis un close() du flux en sortie.

Exemple de lecture des objets depuis un fichier :

package enregistrerDesObjetsChats;
/**============================================
	Lecture d'objet dans un Fichier texte
	Gestion des flux entrée / sortie
	Auteur 			: Philippe Bouget
	Année			  : 2019
	Nom Programme	: LireObjet.java
==============================================
 */
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
public class LireObjet
{
	public static void main (String args[])
	{
		try
		{
			FileInputStream fichierDObjets = new FileInputStream("ChatObj.txt");
			ObjectInputStream fluxDObjets = new ObjectInputStream(fichierDObjets);
			while(true)	// tant qu'il y a des objets
			{
				Object o = fluxDObjets.readObject();
				if (o instanceof Chat)
				{
					((Chat)o).afficher();
				}
				else
				{
					System.out.println("Objet Non Identifié !");
				}
			}
		}
		catch (ClassNotFoundException e) {e.getMessage();}
		catch (IOException e) {e.getMessage();}
		System.out.println("Fin de la lecture");
	}
}

Pour la lecture des objets on déclare un objet du type ObjectInputStream qui nous permet de faire appel à la méthode readObject() pour sauvegarder un objet.