Java 5.fichier

Télécharger au format pdf ou txt
Télécharger au format pdf ou txt
Vous êtes sur la page 1sur 28

POO – JAVA

Partie IV
Les entrées / Sorties
Noreddine Gherabi
Introduction
§ Un programme a souvent besoin de lire des données
depuis une source externe ou d’écrire des données vers
un destinataire externe.
§ La source et la destination de ces échanges peuvent être
de natures multiples : fichier, socket réseau...
§ De même, la nature des données échangées peut être
diverse : texte, images, son...

fichier entrée sortie


programme
lecture écriture
réseau
Les flux
q En java, le mécanisme de flux (‘stream’) permet de
représenter tous ces processus d’envoi/réception de
données.
q Les flux traitent toujours les données de façon
séquentielle (cf. fichiers séquentiels en cours) :
§ à l’ouverture du flux, la position courante est définie (ex: au
début d’un fichier ouvert en lecture);
§ dès qu’une donnée est lue ou écrite, la position courante avance;
le flux n’a aucune mémoire et donne toujours accès à une seule
donnée à un instant donné.
ouverture du flux
tant qu’il reste des données
lecture/écriture d’une donnée dans le flux
fin tant que
fermeture du flux
Les catégories de flux
Les flux
q les flux d’entrée (lecture) et les flux de sortie (écriture),
q les flux de caractères (textes, html, xml…) et les flux d’octets
(nombres entiers/réels, images, sons…).
§ Package java.io : toutes les classes de gestion des flux
§ Les noms des classes se décomposent en un préfixe suivi d’un
suffixe.
§ Suffixes (classes abstraites de flux):
Flux de Flux d’octets
caractères
Flux entrée Reader InputStream
Flux sortie Writer OutputStream

§ Préfixes: indiquent avec quoi le flux communique (File, Object,


String) ou le type de traitements (filtre) associé (Buffered, Data…).
Les classes IO
q On obtient ainsi un grand nombre de classes :

§ FileReader (fichier caractères en lecture),


§ FileWriter (fichier caractères en écriture),
§ BufferedReader (fichier caractères avec tampon en lecture),
§ BufferedWriter (fichier de caractères avec tampon en
écriture),
§ FileInput Stream (fichier octets en lecture),
§ FileOutputStream (fichier octets en écriture),
§ ObjectInputStream (fichier d’objets en lecture),
§ ObjectOutputStream (fichier d’objets en écriture), etc.
Les classes IO
Les flux de caractères
§ Transportent des données sous forme de caractères
(unicode) sur 2 octets.
§ Les classes qui gèrent les flux de caractères héritent
d’une des deux classes abstraites Reader ou Writer.
1- La classe abstraite Reader: flux de caractères en lecture :
§ int read( ) : renvoie le caractère lu (entier dont la valeur est le
code unicode du caractère lu) ou -1 si la fin du flux est atteinte.
§ int read(char[ ]) : lit plusieurs caractères et les place dans un
tableau de caractères, retourne le nombre de caractères lus ou
-1 si la fin du flux est atteinte.
§ void close( ) : ferme le flux et libère les ressources associées.
Ces méthodes peuvent lever des IOException qui
doivent être interceptées ou remontées.
Les classes IO
2. La classe abstraite Writer = flux de caractères en
écriture :
§ void write(int) : écrit le caractère en paramètre (entier
interprété en unicode) dans le flux.
§ void write(String) : écrit la chaîne de caractères en paramètre
dans le flux.
§ void close( ) : ferme le flux et libère les ressources.
Ces méthodes peuvent lever des IOException.
3. La classe concrète FileReader = flux de caractères en
lecture sur un fichier.
§ Plusieurs constructeurs qui peuvent lever une
FileNotFoundException (dérive de IOException). Le plus courant
ouvre un fichier texte en lecture à partir de son nom.
FileReader fich = new FileReader("monfichier.txt");
§ read et close sont héritées de Reader.
Les classes IO
4. La classe concrète FileWriter =flux de caractères en
écriture sur un fichier.
§ Plusieurs constructeurs qui peuvent lever une exception
FileNotFoundException :
FileWriter(String) : si le nom du fichier n’existe pas alors le
fichier est créé; sinon, le flux est ouvert en écriture vers ce
fichier (dont les données sont écrasées).
FileWriter(String, boolean) : le booléen permet de préciser si
les données sont ajoutées en fin de fichier (valeur true) ou
écrasent les données existantes (valeur false).
FileWriter fich = new FileWriter ("monfichier.res");
§ write et close sont héritées de Writer.
Les classes IO
Les flux de caractères « bufferisés »
§ Mise en tampon des données pour traiter un ensemble
de caractères représentant une ligne plutôt que lire/
écrire caractère par caractère (amélioration des
performances).
§ La classe concrète BufferedReader = flux de caractères
bufferisé en lecture :
§ constructeur :
BufferedReader(Reader) : le paramètre fourni doit correspondre
au flux à lire. Le sous typage permet de passer en paramètre la
référence à un objet de n’importe quelle sous-classe de Reader.
BufferedReader fich = new BufferedReader(new
FileReader ("monfichier.txt"));
Les classes IO
§ En plus des méthodes read héritées de la classe Reader,
BufferedReader propose une méthode de lecture ligne par
ligne qui peut lever une IOException :
String readLine( ) : lit la prochaine ligne de caractères dans
le flux. Une ligne est une suite de caractères qui se termine
par un retour chariot '\r' ou un saut de ligne '\n' ou les
deux. Rend null en fin de fichier. Sinon, rend la ligne
§ close héritée de Reader.
Ex: programme de recopie à l’écran d’un fichier de texte.
Exemple
import java.io.*;
public class TestBufferedReader {
private String source;
public TestBufferedReader(String src) {
this.source = src;
}
public static void main(String[ ] args) {
new TestBufferedReader("source.txt").lecture( );
}
public void lecture( ) {
try {
String ligne ;
BufferedReader fichier = new BufferedReader(new FileReader(source));
while ((ligne = fichier.readLine( )) != null) { // lecture et test (pratique !)
System.out.println(ligne);
}
fichier.close( );
} catch (IOException e) {
e.printStackTrace( );
} } }
Les classes IO
6. La classe concrète BufferedWriter = flux de caractères
bufférisé en écriture :
§ Constructeur
BufferedWriter(Writer) : le paramètre correspond au flux à
écrire. Le sous typage permet de passer en paramètre la
référence à un objet de n’importe quelle sous-classe de Writer.
BufferedWriter fich = new BufferedWriter(new FileWriter
("monfichier.txt"));
§ En plus des méthodes write héritées de Writer, Buffered Writer
redéfinit les méthodes d’écriture de façon à les optimiser. La
méthode newLine permet d’écrire un séparateur de ligne.
void newLine( ) : écrit un séparateur de ligne (peut lever une
IOException).
§ close héritée de Writer.
Exemple
import java.io.*;
public class TestBufferedWriter {
private String dest;
public TestBufferedWriter(String d) {
this.dest = d; }
public static void main(String[ ] args) {
new TestBufferedWriter("print.txt").traitement( ); }
public void traitement( ) {
try {
int nombre = 123;
BufferedWriter fichier = new BufferedWriter(new FileWriter(dest));
fichier.write("Bonjour");
fichier.newLine( );
fichier.write("Le nombre est "); Ecrit :
fichier.write(": " + nombre); Bonjour
fichier.newLine( ); Le nombre est : 123
fichier.close( ); dans un fichier.
} catch (IOException e) {
e.printStackTrace( );
} } }
Les classes IO
Les flux d’octets
§ Transportent des données binaires sous forme d’octets.
Ils peuvent traiter toutes les données.
§ Les classes qui gèrent les flux d’octets héritent d’une
des classes abstraites InputStream ou OutputStream.
7. La classe abstraite InputStream = flux d’octets en
lecture :
§ int read( ) : renvoie l’octet lu (entier entre 0 et 255) ou -1 si la
fin du flux est atteinte.
§ int read(byte[ ]) : lit plusieurs octets et les place dans un
tableau d’octets. Retourne le nombre d’octets lus ou -1 si la fin
du flux est atteinte.
N.B. : byte est un type entier codé sur un seul octet.
§ void close( ) : ferme le flux et libère les ressources associées.
Ces méthodes peuvent lever des IOException.
Les classes IO
8. La classe abstraite OutputStream = flux d’octets en
écriture :
§ void write(int) : écrit l’octet en paramètre (poids faible de l’int)
dans le flux.
§ void write(byte [ ]) : écrit le tableau d’octets dans le flux.
§ void close( ) : ferme le flux et libère les ressources.
Ces méthodes peuvent lever des IOException.
9. La classe concrète FileInputStream = flux d’octets en
lecture sur un fichier :
§ Plusieurs constructeurs qui peuvent lever une FileNotFound
Exception. Le plus courant ouvre un fichier d’octets en lecture à
partir de son nom.
FileInputStream fich = new FileInputStream ("monfichier.dat");
§ read et close sont héritées de InputStream.
Les classes IO

10. La classe concrète FileOutputStream = flux d’octets en


écriture sur un fichier :
§ Plusieurs constructeurs qui peuvent lever une FileNotFound
Exception, en particulier :
FileOutputStream(String) : si le nom du fichier n’existe pas
alors le fichier est créé; sinon, le flux est ouvert en écriture vers
ce fichier (dont les données sont écrasées).
FileOutputStream fich = new FileOutputStream
("monfichier.dat");
§ write et close sont héritées de OutputStream.

Ex : programme de copie d’un fichier quelconque octet


par octet.
Exemple
import java.io.*;
public class CopieFichier {
private String source, destination;
public CopieFichier(String src, String dest) {
this.source = src; this.destination = dest;}
public static void main(String[ ] args) {
new CopieFichier("source","copie").copie( ); }
public void copie( ) {
try {
FileInputStream fis = new FileInputStream(source);
FileOutputStream fos = new FileOutputStream(destination);
int oc=fis.read( ); // ou bien int oc=0;
while(oc != -1) { // while((oc = fis.read()) != -1) {
fos.write(oc); // fos.write(oc);
oc=fis.read( ); // }
}
fis.close( ); fos.close( );
} catch (IOException e) {
e.printStackTrace( );
} } }
Les classes IO
Les flux de données binaires
§ Lire un flux d’octets octet par octet n’est pas toujours
pratique. Les classes DataInputStream et DataOutput
Stream permettent de lire/écrire directement des
données typées entières, réelles, booléennes...
11. La classe concrète DataInputStream = flux de données
typées en lecture :
§ Constructeur
DataInputStream(InputStream) : crée un flux de données
typées en lecture à partir du flux d’octets en paramètre.
DataInputStream fich = new DataInputStream(new
FileInputStream("monfichier.dat"));
Les classes IO

En plus des méthodes héritées de InputStream, la classe


DataInputStream définit des méthodes pour lire des
données typées :
boolean readBoolean() : lit un booléen (un octet).
int readInt() : lit un entier (4 octets).
double readDouble() : lit un réel (8 octets).
Ces méthodes peuvent lever des EOFException si la fin de flux a été
atteinte ou des IOException si une erreur d’E/S s’est produite.
§ close() est héritée de InputStream.
Les classes IO

12. La classe concrète DataOutputStream = flux de


données typées en écriture :
§ Constructeur
DataOutputStream(OutputStream) : crée un flux de données
typées en écriture à partir du flux d’octets en paramètre.
DataOutputStream fich = new DataOutputStream
(new FileOutputStream("monfichier.out"));
§ En plus des méthodes write héritées de la classe Output Stream,
la classe DataOutputStream définit plusieurs méthodes pour
écrire des données typées :
void writeBoolean(boolean) : écrit le booléen en paramètre.
void writeInt(int) : écrit l’entier en paramètre.
void writeDouble(double) : écrit le réel en paramètre.
La sérialisation
Les flux d’objets –
§ La sérialisation permet d’écrire (puis lire) des objets dans des
flux d’octets. Java transforme l’objet et tous les objets qui lui
sont liés en une suite d’octets qui peut à son tour être
réinterprétée comme l’objet initial.

§ C’est au programmeur de vérifier que les objets qu’il


manipule sont sérialisables (c.à.d. que la transformation peut
leur être appliquée). Le programmeur l’indique en précisant
que la classe implémente l’interface prédéfini Serializable.

§ Un objet est sérialisable si tous ses attributs d’instance sont :


§ soit d’un type de base de Java (int, double…).
§ soit d’un type objet sérialisable.
Exemple
public class A {
private int x; // A est sérialisable
}
public class B {
private double v; // B est sérialisable (car A l’est)
private A refA;
}

Pour permettre à Java de sérialiser (transformer en octets) les objets


de A et B il faut écrire :

public class A implements Serializable {


private int x;
}
public class B implements Serializable {
private double v;
private A refA;
}
La sérialisation
§ On peut lire et écrire des objets sérialisables dans des flux
d’octets grâce aux classes ObjectInputStream et
ObjectOutputStream.
13. La classe concrète ObjectInputStream = flux d’objets en lecture :
§ Constructeur ObjectInputStream (InputStream).
§ La classe propose les mêmes méthodes de lecture que
DataInputStream. Elle propose en plus une méthode de
lecture d’un objet aussi complexe soit-il.
Object readObject() : lit un objet (taille quelconque).
Le type retourné est Object. Il faut en général “caster” pour
utiliser l’objet dans son type d’origine.
Peut lever des exceptions liées aux E/S (IOException) ou à la
sérialisation (attrapées par Exception).
La sérialisation

14.La classe concrète ObjectOutputStream = flux d’objets


en écriture :
§ Constructeur ObjectOutputStream (OutputStream).
§ La classe propose les mêmes méthodes d’écriture que
DataOutputStream. Elle propose en plus une méthode
d’écriture d’un objet aussi complexe (mais sérialisable).
void writeObject(Object) : écrit un objet via la sérialisation
(taille quelconque).
Il faut noter que le type du paramètre est Object, ce qui
permet d’écrire (par sous-typage) n’importe quel type d’objet.
Peut lever diverses sortes d’exceptions liées aux E/S
(IOException).
§ close héritée de OutputStream.
Exemple
Exemple : écriture d’un point et relecture
import java.io.*;
class UnPoint implements Serializable {
private int abscisse,ordonnee;
public UnPoint(int x,int y) {
abscisse=x;
ordonnee=y;
}
}
public class TestObjectStreams {
private UnPoint point;
private String nomf; // nom fichier
public TestObjectStreams(UnPoint pt,String nf) {
this.point = pt;
this.nomf = nf;
}
public static void main(String[] args) {
TestObjectStreams tos=new TestObjectStreams(new UnPoint(20,30), "ficobj");
tos.sauve();
tos.charge();
}
Exemple : Suite
public void sauve() {
try {
ObjectOutputStream oos=new ObjectOutputStream(new
FileOutputStream(nomf));
oos.writeObject(point);
oos.close();
} catch (IOException e) {
System.out.println("erreur d'E/S");
} catch (Exception e) {
System.out.println("erreur hors E/S");
}
}
public void charge() {
try {
ObjectInputStream ois=new ObjectInputStream(new
FileInputStream(nomf));
point=(UnPoint)(ois.readObject());
ois.close();
} catch (IOException e) {
System.out.println("erreur d'E/S");
} catch (Exception e) {
System.out.println("erreur hors E/S");
}
} }
la classe Scanner
§ Facilite la lecture dans un flux.
Particulièrement utile pour lire des données à partir du
clavier (System.in) dans une application de type console.
System.in est un InputStream
System.out est un PrintStream
La méthode next() bloque l’exécution jusqu’à la lecture
de données et les renvoie sous la forme d’une chaîne de
caractères.
Ex :
public class TestScanner {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String s = scanner.next();
scanner.close();
}
}
la classe Scanner
§ nextInt(), nextDouble(), ... :
les méthodes nextTYPE() où TYPE représente un type de
base bloquent l’exécution jusqu’à la lecture de données,
tentent de les convertir dans le type TYPE et lèvent une
exception InputMismatchException si les données lues
ne peuvent pas être converties.
§ hasNextInt(), hasNextDouble(), hasNextBoolean(),… :
Les méthodes hasNextTYPE() retournent un booléen qui
indique si les données peuvent être interprétées comme
étant de type TYPE.
Ex :
System.out.print(«Entier suivant=»);
if (scanner.hasNextInt()) {
n = scanner.nextInt();
} else {
System.out.println(«Type errone:» + scanner.next());
}

Vous aimerez peut-être aussi