Introduction. Inconvénient : au départ ça paraît un peu compliqué

47  Download (0)

Full text

(1)

LES ENTREÉS/SORTIES

(2)

Les entrées/sorties

• Introduction

• Grandes catégories de flux

• Flux physiques / Flux logiques

• Compositions des flux

• Gestion des exceptions / fermeture

• Flux d’entrées/sorties standards

• Flux de données / Flux d’objets

• Fichiers à accès direct

(3)

Entrées/Sorties en Java

➔package java.io

➔ vision unifiée de toutes les opérations d'entrées/sorties sous forme de flux séquentiels (Stream)

Flux (Stream) : élément dans lequel on pourra effectuer

➔des opérations de lecture séquentielles : flux d'entrée

➔des opérations d’écriture séquentielles : flux de sortie Intérêt : uniformité

➔on utilise les mêmes opérations, pour lire/écrire

➔dans un fichier,

➔dans entrées/sorties standards,

➔via le réseau

➔etc…

Inconvénient : au départ ça paraît un peu compliqué…

Introduction

(4)

4 grandes catégories de flux :

Les 4 grandes catégories de flux

Flux d'octets Flux de caractères Flux d'entrée InputStream Reader

Flux de sortie OutputStream Writer

(5)

Pour chaque catégorie d'éléments qu'on peut utiliser en entrée/sortie, on aura une sous classe…

Les sous-catégories de flux

fichier

flux d'objets

types primitifs

concaténation de flux

flux

bufférisé

(6)

Pour chaque catégorie d'éléments qu'on peut utiliser en entrée/sortie, on aura une sous classe…

Les sous-catégories de flux

fichier

flux d'objets

types primitifs

flux

bufférisé

(7)

Pour chaque catégorie d'éléments qu'on peut utiliser en entrée/sortie, on aura une sous classe…

Les sous-catégories de flux

fichier numérotation des lignes

Chaîne de caractères transformation

d'un flux d'octets

en flux de caractères

(8)

Pour chaque catégorie d'éléments qu'on peut utiliser en entrée/sortie, on aura une sous classe…

Les sous-catégories de flux

avec un buffer

Fichier

Chaîne de caractères

(9)

Flux physiques

• Les classes InputStream/OutputStream/Reader/Writer définissent les méthodes de base:

– lecture / écriture d’octets / de caractères

• Elles sont déclinées pour différents types de supports

– Fichiers

➔ FileInputStream/FileOutputStream

➔ FileReader/FileWriter – Tableaux

➔ ByteArrayInputStream/ByteArrayOutputStream

➔ CharArrayInputStream/CharArrayOutputStream – String

➔ StringReader/StringWriter

(10)

Flux logiques

• D’autres classes permettent de transformer des flux

– Transformation de flux d’octets en flux de caractères

• InputStreamReader/OutputStreamWriter

• Ou leur ajouter des fonctionnalités

– Ajout d’un buffer

• BufferedInputStream/BufferedOutputStream

• BufferedReader/BufferedWriter

– Ajout de méthodes print

• PrintStream/ PrintWriter

– Lecture écriture d’objets binaires

• DataInputStream/DataOutputStream (types primitifs)

• ObjectInputStream/ObjectOutputStream (objets java)

– Compression/Décompression

• DeflaterInputStream/DeflaterOutputSream (compression)

• InflaterInputStream/InflaterOutputSream (decompression)

– Etc.

Il existe des sous-classes pour différents formats :

GZip : GZIPInputStream GZIPOutputStream Zip : ZipInputStream

ZipOutputStream Jar : JarInputStream

JarOutputStream

(11)

Exemple écriture dans un fichier

Écriture de caractères dans un fichier :

// obtention flux de sortie binaire

OutputStream fos = new FileOutputStream("C:/temp/test.txt");

// transformation en flux de charactères

Writer fWriter = new OutputStreamWriter(fos, "UTF-8");

// Ajout d’un buffer

Writer buffWriter = new BufferedWriter(fWriter);

// transformation en PrintWriter

PrintWriter pOut = new PrintWriter(buffWriter);

// Ecriture dans le fichier avec les méthodes print pOut.println("Hello World!");

pOut.println(Math.PI * 3.0);

// fermeture des flux (une fois qu’on n’en a plus besoin) pOut.close();

Remarque : si on ne précise pas l’encodage, l’encodage par défaut de la vm java est utilisé

(12)

Exemple écriture dans un fichier

• On part d’un flot basique (FileOutputStream) et

• On l’encapsule dans un ou plusieurs flux pour

• le transformer ou

• ajouter des nouvelles fonctionnalités

new PrintWriter(

new BuffererdWriter(

new OutputStreamWriter(

new FileOutputStream("C:/temp/test.txt")

"UTF-8")))

FileOutputStream OutputStreamWriter

BufferedWriter

PrintWriter

(13)

Exemple écriture dans une chaîne de caractères

Écriture dans une chaîne de caractères :

// obtention flux de sortie de type caractères Writer sWriter = new StringWriter();

// Ajout d’un buffer

Writer buffWriter = new BufferedWriter(sWriter);

// transformation en PrintWriter

PrintWriter pOut = new PrintWriter(buffWriter);

// Ecriture dans le fichier avec les méthodes print pOut.println("Hello World!");

pOut.println(Math.PI * 3.0);

// fermeture des flux (une fois qu’on n’en a plus besoin) pOut.close();

// Récupération de la chaine de caractères

String s = sWriter.toString();

(14)

Exemple écriture dans une chaîne de caractères

• On part d’un flot basique (StringWriter) et

• On l’encapsule dans un ou plusieurs flux pour

• le transformer ou

• ajouter des nouvelles fonctionnalités

new PrintWriter(

new BuffererdWriter(

new StringWriter() ) )

StringWriter BufferedWriter

PrintWriter

(15)

Méthodes importantes

Méthodes pour java.io.InputStream :

• void close() fermeture du flux.

• int available() nombre d'octets disponibles sur le flux.

Lecture

• abstract int read() lecture d'un octet.

• int read(byte[ ] b) utilisation d'un tableau d'octets comme buffer.

• int read(byte[ ] b, int off, int len) idem.

Déplacement

• long skip(long n) on saute n octets.

Repositionnement

• boolean markSupported() si les méthodes mark et reset sont utilisables.

• void mark(int readlimit) mémorisation de la position actuelle.

• void reset() on revient à la position mémorisée avec mark.

(16)

Méthodes importantes

Méthodes pour java.io.Reader :

• void close() fermeture du flux.

• boolean ready() indique si le flux est prêt pour une lecture.

Lecture

• abstract int read() lecture d'un caractère.

• int read(char[ ] cbuf) utilisation d'un tableau de caractères comme buffer.

• int read(char[ ] cbuf, int off, int len) idem.

Déplacement

• long skip(long n) on saute n caractères.

Repositionnement

• boolean markSupported() si les méthodes mark et reset sont utilisables.

• void mark(int readlimit) mémorisation de la position actuelle.

• void reset() on revient à la position mémorisée avec mark.

(17)

Méthodes importantes

Méthodes pour java.io.OutputStream :

• void close() fermeture du flux.

• boolean flush() force l'écriture des octets (utile si il y a un buffer).

Écriture

• abstract void write(int b) écriture d'un octet.

• void write(byte[ ] b) utilisation d'un tableau d'octets.

• void write(byte[ ] b, int off, int len) idem.

Méthodes pour java.io.Writer :

• void close() fermeture du flux.

• boolean flush() force l'écriture des caractères (utile si il y a un buffer).

Écriture

• abstract void write(int b) écriture d'un caractère.

• void write(char[ ] cbuf) utilisation d'un tableau de caractères.

• void write(char[ ] cbuf, int off, int len) idem.

• void write(String str) utilisation d'une chaîne de caractères.

• void write(String str, int off, int len) idem.

(18)

Méthodes importantes

Méthodes pour java.io.PrintStream et java.io.PrintWriter :

PrintStream(OutputStream out)

PrintStream(OutputStream out, boolean autoFlush, String encoding)

PrintWriter(OutputStream out)

PrintWriter(OutputStream out, boolean autoFlush)

PrintWriter(Writer out)

PrintWriter(Writer out, boolean autoFlush) Écriture

• void print(boolean b)

• void println(boolean b)

• void print(char c)

• void println (char c)

• …

• void print(String s)

• void println(String s)

• void print(Object obj)

• void println (Object obj)

(19)

Méthodes importantes

Méthodes pour BufferedReader et BufferedWriter :

java.io.BufferedReader

BufferedReader(Reader in)

BufferedReader(Reader in, int sz)

• String readLine() Read a line of text.

java.io.BufferedWriter

BufferedWriter(Writer out)

BufferedWriter(Writer out, int sz)

• void newLine() Write a line separator.

(20)

Fermeture des flux Gestion des exceptions

• Fermeture des flux :

– Une fois qu’on a fini d’utiliser un flux, il faut le fermer

• méthode close()

– Les plupart des méthodes de lecture/écriture peuvent générer des exceptions ( java.io.IOException )

• On va les capturer avec

try catch

try-with-resources catch

(21)

Fermeture des flux Gestion des exceptions

• Exemple avec try catch :

InputStream in = new FileInputStream("C:/temp/test.ppt");

OutputStream out = new FileOutputStream("C:/temp/test2.ppt");

try {

int b = in.read();

while (b != -1) { out.write(b);

b = in.read();

}

}

catch

(IOException e) {

System.err.println("erreur sur le flux");

} finally { in.close();

out.close();

}

Peut générer des exceptions

Peut générer des exceptions

Peut générer des exceptions

Les flux doivent être fermés quand on n’en a plus besoin

Problème : la fermeture des flux peut aussi générer des exceptions

(22)

Fermeture des flux Gestion des exceptions

• Exemple avec try-with-resources catch :

try (

InputStream in = new FileInputStream("C:/temp/test.ppt");

OutputStream out = new FileOutputStream("C:/temp/test2.ppt") ){

int b = in.read();

while (b != -1) { out.write(b);

b = in.read();

}

}

catch

(IOException e) {

System.err.println("erreur sur le flux");

}

• Les ressources définies dans le try-with-resources sont automatiquement fermées à la fin du try catch

Peut générer des exceptions

Peut générer des exceptions

Peut générer des exceptions

Les flux sont automatiquement fermés à la fin du try catch

(23)

Les Entrées/Sorties standards

La classe System permet d'accéder aux 3 flux standards :

System.in ➔ flux d'entrée "standard" (par défaut → clavier)

System.out ➔ flux de sortie "standard" (par défaut → console écran) – System.err ➔ flux d'erreur "standard" (par défaut → console écran)

Types de flux associés aux flux standards :

System.in → java.io.InputStream – System.out → java.io.PrintStream – System.err → java.io.PrintStream

Changement des flux standards :

System.setIn (InputStream in )

System.setOut (PrintStream out )

System.setErr (PrintStream err )

(24)

Exemple

Écriture sur le flux de sortie Standard :

System.out.println("Bonjour, ");

System.out.print("écriture d'un réel (PI): ");

double pi = Math.PI;

System.out.println(pi);

Lecture d'un entier sur le flux d'entrée Standard :

InputStreamReader in0 = new InputStreamReader(System.in);

BufferedReader in1 = new BufferedReader(in0);

try {

String s = in1.readLine();

int k = Integer.parseInt(s);

} catch (IOException e) {

System.err.println("erreur de lecture sur le flux");

} catch (NumberFormatException e) {

System.err.println("erreur de conversion de l'entier");

}

(25)

Exemple

Copie d'un fichier :

InputStream in = new FileInputStream("C:/temp/test.ppt");

OutputStream out = new FileOutputStream("C:/temp/test2.ppt");

try {

int b = in.read();

while (b != -1) { out.write(b);

b = in.read();

}

} catch (IOException e) {

System.err.println("erreur sur le flux");

} finally { in.close();

out.close();

}

(26)

Exemple : avec un pipe

Coté producteur :

public class Producteur implements Runnable { private PipedWriter out;

public Producteur(PipedWriter out) { this.out = out;

}

public void run(){

try {

out.write("Hello\n");

out.write("World\n");

} catch (IOException e) {

System.err.println("erreur d'écriture");

} finally { out.close();

} } }

(27)

Exemple : avec un pipe

Coté consommateur :

public class Consommateur implements Runnable { private PipedReader in;

public Consommateur(PipedReader in) { this.in = in;

}

public void run(){

try ( BufferedReader in = new BufferedReader(this.in)){

String s = in.readLine();

while (s != null) {

System.out.println("lecture de : "+ s );

s = in.readLine();

}

} catch (IOException e) {

System.err.println("erreur d'écriture");

} } }

(28)

Exemple : avec un pipe

Lancement des processus :

PipedReader in = new PipedReader();

PipedWriter out = new PipedWriter();

try {

out.connect(in);

Thread tProd = new Thread(new Producteur(out));

Thread tCons = new Thread(new Consommateur(in));

tProd.start();

Thread.sleep(10);

tCons.start();

}

catch

(Exception e) {

}

(29)

Exemple : avec un pipe

Coté producteur :

public class Producteur implements Runnable { private Writer out;

public Producteur(Writer out) { this.out = out;

}

public void run(){

try {

out.write("Hello\n");

out.write("World\n");

} catch (IOException e) {

System.err.println("erreur d'écriture");

} finally { out.close();

} } }

(30)

Exemple : avec un pipe

Coté consommateur :

public class Consommateur implements Runnable { private BufferedReader in;

public Consommateur(Reader in) { this.in = new BufferedReader(in);

}

public void run(){

try {

while (in.ready()) {

String s = in.readLine();

System.out.println("lecture de : "+ s );

}

} catch (IOException e) {

System.err.println("erreur de lecture");

} finally { in.close();

} } }

(31)

Exemple : avec des sockets

Sur le serveur

//port d'écoute du listener

ServerSocket ssServer=new ServerSocket(8080);

Socket sSocket=null;

//on attend en attendant une connexion cliente while(sSocket==null){

sSocket=ssServer.accept();

}

Writer out = new OutputStreamWriter(sSocket.getOutputStream());

Thread tProd = new Thread(new Producteur(out));

tProd.start();

sur le client

// connection

Socket sSocket=new Socket("127.0.0.1",8080);

Reader in = new InputStreamReader(sSocket.getInputStream());

//creation et lancement du client

Thread tCons = new Thread(new Consommateur(in));

tCons.start();

(32)

On écrire/lire des entiers, réels,… sur des flux d'entrées/sorties

➔flux de sortie : java.io.DataOuputStream

➔flux d'entrée : java.io.DataInputStream

Écriture : pour chaque type primitif on aura une méthode spécifique

➔void writeBoolean(boolean b)

➔void writeInt(int i)

➔void writeDouble(double r)

➔…

Lecture : pour chaque type primitif on aura une méthode spécifique

➔boolean readBoolean( )

➔int readInt( )

➔double readDouble( )

➔…

Format utilisé : format binaire (pas utilisable pour les flux standards)

Flux de données primitives

(33)

Flux de données

Flux en écriture : java.io.DataOutputStream

Constructeur :

DataOutputStream ( OutputStream in ) constructeur du flux.

Écriture de données de type primitif

– void writeBoolean(boolean b) écriture d'un booléen

– void writeByte(int b) écriture d'un octet

– void writeChar(int c) écriture d'un caractère

– void writeShort(int i)

– void writeInt(int i) écriture d'un entier

– void writeLong(long l)

– void writeFloat(float v) lecture d'un float

– void writeDouble(double v) lecture d'un double

– void writeUTF(String s) écriture d'une String au format UTF-8

(34)

Flux de données

Flux en lecture : java.io.DataInputStream

Constructeur :

DataInputStream ( InputStream in ) constructeur du flux.

Lecture de données de type primitif

– boolean readBoolean() lecture d'un booléen

– byte readByte() lecture d'un octet

– char readChar() lecture d'un caractère

– short readShort()

– int readInt() lecture d'un entier

– int readUnsignedByte() – int readUnsignedShort() – long readLong()

– float readFloat() lecture d'un float

– double readDouble() lecture d'un double

– String readUTF() lecture d'un chaîne de caractère au format UTF-8

(35)

Exemple : flux de données

Sauvegarde de types primitifs :

OutputStream fos = new FileOutputStream("C:/temp/test.data");

DataOutputStream dos = new DataOutputStream(fos);

double[] tab = {1.0,2.0,3.0,4.0,5.0,6.0} ; try {

dos.writeBoolean(tab != null);

dos.writeInt (tab.length);

for (int i=0; i < tab.length ; i++){

dos.writeDouble(tab[i]);

}

}

catch

(IOException e) {

System.err.println("erreur sur le flux");

} finally {

dos.close();

}

(36)

Exemple : flux de données

Récupération de types primitifs :

InputStream fis = new FileInputStream("C:/temp/test.data");

DataInputStream dis = new DataInputStream(fis);

double[] tab = null;

try {

// on regarde si le tableau n'était pas vide...

if (dis.readBoolean()) {

// on lit la taille du tableau int taille = dis.readInt();

tab = new double[taille];

for (int i=0; i < taille ; i++){

tab[i] = dis.readDouble();

} }

} catch (IOException e) {

System.err.println("erreur sur le flux");

} finally {

dis.close();

}

(37)

Exemple : avec des tableaux

Sauvegarde :

...

ByteArrayOutputStream bOut = new ByteArrayOutputStream();

DataOutputStream dos = new DataOutputStream(bOut);

double[] tab = {1.0,2.0,3.0,4.0,5.0,6.0} ; try {

// on regarde si le tableau n'était pas vide...

if (dos.writeBoolean(tab != null)) { ...

Récupération

...

InputStream bIn = new ByteArrayInputStream(bOut.toByteArray());

DataInputStream dis = new DataInputStream(bIn);

double[] tab = null;

try {

// on regarde si le tableau n'était pas vide...

if (dis.readBoolean()) { ...

(38)

On peut utiliser les flux d'entrées/sorties pour sauver des objets java :

➔flux de sortie : java.io.ObjectOutputStream

➔flux d'entrée : java.io. ObjectInputStream

Écriture d'un objet : par défaut le système sauvegarde

➔la classe de l'objet et tous les attributs sauf

➔les attributs static (car ils sont sur la classe) et

➔les attributs transient

➔si un attribut contient un objet, cet objet est lui aussi sauvé !

Lecture d'un objet : comme l'écriture mais en sens inverse Contrainte :

➔l'objet doit être sérialisable : i.e. implanter java.io.serializable

➔tous les attributs à sauver doivent être

➔soit de type primitif (boolean, int, float, double, …)

➔soit sérialisables (et implanter aussi java.io.serializable)

Flux d'Objets

(39)

Flux d'Objets

Flux en écriture : java.io.ObjectOutputStream

Constructeur :

ObjectOutputStream ( OutputStream in ) constructeur du flux.

Écriture

– void writeBoolean(boolean b) écriture d'un booléen

– void writeByte(int b) écriture d'un octet

– void writeChar(int c) écriture d'un caractère

– void writeShort(int i)

– void writeInt(int i) écriture d'un entier

– void writeLong(long l)

– void writeFloat(float v) lecture d'un float

– void writeDouble(double v) lecture d'un double

– void writeUTF(String s) écriture d'une String au format UTF-8

– void writeObject(Object obj) écriture d'un objet sérialisable

(40)

Flux d'Objets

Flux en lecture : java.io.ObjectInputStream

Constructeur :

ObjectInputStream ( InputStream in ) constructeur du flux.

Lecture

– boolean readBoolean() lecture d'un booléen

– byte readByte() lecture d'un octet

– char readChar() lecture d'un caractère

– short readShort()

– int readInt() lecture d'un entier

– int readUnsignedByte() – int readUnsignedShort() – long readLong()

– float readFloat() lecture d'un float

– double readDouble() lecture d'un double

– String readUTF() lecture d'un chaîne de caractère au format UTF-8

– Object readObject() lecture d'un objet sérialisable

(41)

Exemple1 : flux d'objets

Sauvegarde des objets:

OutputStream fos = new FileOutputStream("C:/temp/test.obj");

ObjectOutputStream oos = new ObjectOutputStream(fos);

double[] tab = {1.0, 2.0, 3.0, 4.0, 5.0, 6.0} ; try {

oos.writeObject(tab);

} catch (IOException e) {

System.err.println("erreur sur le flux");

} finally { oos.close(); }

Récupération des objets :

InputStream fis = new FileInputStream("C:/temp/test.obj");

ObjectInputStream ois = new ObjectInputStream(fis);

double[] tab = null;

try {

tab = (double[])ois.readObject();

} catch (IOException e) {

System.err.println("erreur sur le flux");

} catch (ClassNotFoundException e) {

System.err.println("Type d'objet inconnu");

} finally { ois.close(); }

(42)

Exemple2 : flux d'objets

Sauvegarde des objets : exemple classe Personne

public class Personne implements Serializable {

static private final long serialVersionUID = 6L;

private String nom;

private String adresse;

public Personne(String nom, String adresse){

this.nom = nom;

this.adresse = adresse;

}

public String toString(){

return nom + " - " + adresse;

} }

Pour être utilisable dans un flux d’objets la classe doit

être Serializable

Optionnel : permet de vérifier que la classe n’a pas été modifiée entre la sauvegarde et

la restauration d’un objet Les attributs doivent

être Serializable

(43)

Exemple2 : flux d'objets

Sauvegarde des objets:

Personne joe = new Personne("Joe", "1 rue du temple" );

Personne anne = new Personne("Anne", "2 avenue des écoles" );

try ( ObjectOutputStream oos =

new ObjectOutputStream(new FileOutputStream("C:/temp/test.obj")) ){ oos.writeObject(joe);

oos.writeObject(anne);

} catch (IOException e) {

System.err.println("erreur sur le flux");

}

Récupération des objets :

Personne p1, p2;

try ( ObjectInputStream ois =

new ObjectInputStream(new FileInputStream("C:/temp/test.obj")) ){ p1 = (Personne)ois.readObject();

p2 = (Personne)ois.readObject();

} catch (IOException e) {

System.err.println("erreur sur le flux");

} catch (ClassNotFoundException e) {

System.err.println("Type d'objet inconnu");

}

(44)

Système de fichiers : java.io.File

Quelques constructeurs

File(String pathname)

File(File parent, String child)File(URI uri)

Quelques méthodes

– boolean exists( ) – boolean canRead( ) – boolean canWrite( ) – boolean isDirectory( ) – boolean isFile( )

– boolean createNewFile( ) – boolean delete( )

– boolean mkdir( )

– boolean renameTo(File dest) – String getAbsolutePath( ) – URI toURI( )

– String getName( ) – String getParent( ) – String[ ] list( )

– File[ ] listFiles( )

(45)

Choix d'un fichier : IHM

Avec l'AWT : java.awt.FileDialog

FileDialog chooser = new FileDialog(myFrame);

chooser.setMode(FileDialog.LOAD);

chooser.show();

System.out.println("You chose to open this file: " + chooser.getDirectory()+chooser.getFile());

Avec SWING : javax.swing.JFileChooser

JFileChooser chooser = new JFileChooser();

int returnVal = chooser.showOpenDialog(myFrame);

if(returnVal == JFileChooser.APPROVE_OPTION) {

System.out.println("You chose to open this file: " + chooser.getSelectedFile().getAbsolutePath());

}

(46)

Les fichiers à accès direct

Il existe aussi des fichiers à accès direct : java.io.RandomAccessFile

RandomAccessFile(File file, String mode)

RandomAccessFile(String name, String mode)

Lecture :

– int read( ) / int read(byte[ ] b) lecture d'un ou plusieurs octets

– boolean readBoolean( ) lecture d'un booléen

– int readInt( ) lecture d'un entier

Écriture

– void write(byte b) / void write((byte[ ] b)

– void writeBoolean(boolean b) écriture d'un booléen

– void writeDouble(double v) lecture d'un double

Déplacement

– long getFilePointer( ) position actuelle dans le fichier – void seek(long pos) déplacement par rapport au début du fichier – void skipBytes(int n) déplacement par rapport à la position actuelle – long length( ) / void setlength(long newLength) gestion de la taille du fichier – void close( )

(47)

Exemple : fichiers à accès direct

Sauvegarde :

RandomAccessFile f = new RandomAccessFile("c:/temp/test.dat", "rw");

for (int i = 0; i < 10; i++) { f.writeInt(i * 100);

}

f.close();

Récupération (on lit un entier sur 2 en commençant par la fin) :

RandomAccessFile f = new RandomAccessFile("c:/temp/test.dat", "r");

long i = f.length();

while (i >= 4) { f.seek(i-4);

System.out.println(f.readInt());

i = i – (2*4); //un entier fait 4 octets }

f.close();

Figure

Updating...

References

Related subjects :