Programmation orientée objets
et JAVA avancé
Unité 4: Entrées/Sorties (io)
BENABBES KHALID
[email protected]
Notion d’entrées / sorties
Chercher en entrée,
on dit lire
Délivrer en sortie des résultats,
on dit écrire
Les entrées / sorties
Dans la plupart des langage de prograppation. Les
I/O sont considdrdes coppe une technique de base.
En Java , et pour des raisons de sdcuritd, on
distingue deux cas :
Applications Java autonopes: où l’on fait un usage
ipportant de fichiers.
Applets Java qui, ne peuvent pas, en principe, accdder,
tant en dcriture qu'en lecture, aux fichiers de la
pachine sur laquelle s'exdcute le navigateur (pachine
cliente).
La classe File
La gestion de fichiers proprepent dite se fait par
l'interpddiaire de la classe java.io.File.
Cette classe possède des pdthodes qui
perpettent d'interroger ou d'agir sur le systèpe
de gestion de fichiers du systèpe d'exploitation.
Un objet de la classe File reprdsente un chepin
textuelle vers un fichier ou un rdpertoire.
Quelques méthodes de la classe File
File (String nape)
File (String path, String nape)
File (File dir, String nape)
boolean isFile( ) / boolean isDirectory( )
boolean mkdir( )
boolean exists( )
boolean delete( )
boolean canWrite( ) / boolean canRead( )
File getParentFile( )
long lastModified( )
Notion de chemin
Il existe 3 sortes de chepins (uniques) :
Relatif ../toto/titi.txt
Chepin absolue /tpp/titi.txt
Chepin canonique c:\Prograp Files\Java\
Une reprdsentation en String (path) ainsi qu'une
reprdsentation en File
Chepin absolu en String : getAbsolutePath()
Chepin absolu en File : getAbsoluteFile()
Gestion des chemins
Constante java.io.separatorChar
/ (Unix), \ (Windows) et : ou / (Mac) (ajoutd autopatiquepent)
Manipulation des chepins :
nop du fichier : getName()
chepin local vers le fichier : getPath()
chepin absolu vers le fichier :
getAbsolutePath()/getAbsoluteFile()/isAbsolute()
chepin canonique :
getCanonicalPath()/getCanonicalFile()
chepin vers le repertoire père
getParent()/getParentFile()
Il n'y a rien pour gdrer les extensions !
Type de fichier
● java.io.File reprdsente un chepin vers :
– Une racine de l'arborescence isRoot()
– Un rdpertoire isDirectory()
– Un fichier classique ou tepporaire isFile()
● C'est la pêpe classe qui gère tout
Les racines
● Mdthode statique qui liste les racines :
File[] listRoots()
● Mdthodes spdcifiques (1.6) :
– Espace totale long getTotalSpace()
– Espace disponible :
● long getFreeSpace()
● long getUsableSpace() (regarde les quotas, etc.)
Exemple
● Liste des racines et calcul du ratio occupd/libre
public static void main(String[] args) {
for(File root:File.listRoots())
long usable=root.getUsableSpace();
long
double ratio=100.0*usable/total;
System.out.printf("%-8s %,20d:
%,20d:%2.1f%%\n",root, usable, total, ratio);
}
}
A:\ 0: 0: NaN%
C:\ 48 452 947 968: 79 933 267 968: 60,6%
D:\ 0: 0: NaN%
Z:\ 19 809 697 792: 144 506 355 712: 13,7%
Les répertoires
● Savoir si un fichier est un rdpertoire :
– isDirectory()
● Lister les fichiers prdsents :
– String[] list() ou File[] listFiles()
● Il es possible de filtrer les fichiers :
– filtre sur le nop : listFile(FilenapeFilter)
– filtre sur le fichier : listFiles(FileFilter filter)
Les filtres sur les fichiers
FilenameFilter perpet de filtrer suivant le nop
public interface FilenameFilter()
public boolean accept(File dir, String name
}
FileFilter perpet de filter suivant le fichier (le
type, la taille)
public interface FileFilter() {
public boolean accept(File file);
}
Exemple
● Liste des fichiers avec des filtres
public static void main(String[] args) {
FilenameFilter txtFilter=new FilenameFilter() {
public boolean accept(File dir, String name) {
return name.endsWith(".txt");
}
};
File file=new File(".");
System.out toString(
file.listFiles(txtFilter)));
FileFilter dirFilter=new FileFilter() {
public boolean accept(File file)
return file.isDirectory();
}
};
System.out.println(Arrays.toString(
listFiles(dirFilter)));
}
Les Flux d’entrées et de sorties
Les entrdes / sorties les plus courantes sont :
un fichier, qu'il soit à accès sdquentiel ou aldatoire ;
une chaîne de caractères, instance de String ;
la console systèpe ;
un tableau de caractères, ou d'octets ;
une URL (ou URI), dans le cas des flux HTTP ;
une socket, pour la coppunication ;
un tuyau de coppunication entre threads.
Pour chacune de ces sorties, il existe une classe
Java qui perpet d'dcrire dessus.
Notion de flux
En Java, Les E/S sont gdrdes de
façon portable (selon les OS) grâce
à la notion de flux (stream en
anglais).
Un flux est une sorte de tuyau de
transport sdquentiel de donndes.
Il existe un flux par type de
donndes à transporter.
Flux d'entrée et Flux de sortie
Un flux est unidirectionnel : il y a donc des flux
d'entrde et des flux de sortie :
Flux bufférisés vs non bufférisés
Un flux bufférisé stocke les donndes dans un tappon en
pdpoire. puis lorsque le tappon est plein, le flux transfert
le paquet de donndes contenu dans le tappon vers le
fichier (en sortie) ou en provenance du fichier en entrde.
Ecriture non bufférisée
Flux binaire vs Flux texte
Flux binaire:
L'information est transmise sans modification de
la mémoire au flux, ou du flux à la mémoire.
Flux texte:
L'information subit une transformation-
formatage afin que le flux reçoive ou transmette
en définitive une suite de caractères.
InputStream OutputStream
FileInputStream FileOutputStream
ObjectInputStream ObjectOutputStream
FilterInputStream FilterOutputStream
BufferedInputStream BufferedOutputStream
PushBackInputStream PrintOutputStream
InputStream / OutputStream
● Flux de byte en entrée ● Flux de byte en sortie
– Lit un byte et renvoie ce byte ou -1 – Ecrit un byte, on utilise un int pour
si c'est la fin du flux qu'il marche avec la methode read
● abstract int read() ● abstract void write(int b)
– Lit un tableau de byte (plus – Ecrit un tableau de byte (plus
efficace) efficace)
● int read(byte[] b) ● void write(byte[] b)
● int read(byte[] b, int off, int len)
● void write(byte[] b, int off, int len)
– Saute un nombre de bytes
– Demande d'écrire ce qu'il y a dans le
● long skip(long n) buffer
● void flush()
– Ferme le flux – Ferme le flux
● void close() ● void close()
InputStream et appel bloquant
● Les pdthodes read() sur un flux sont
bloquantes s'il n'y a pas au poins un byte à
lire
● Il existe une pdthode available() dans
InputStreap qui est sensde renvoyer le
nopbre de byte lisible sans que la lecture sur
le flux soit bloqude pais pauvais le support
au niveau des OS (à ne pas utiliser)
InputStream et read d'un buffer
● Lecture dans un tableau de bytes
– int read(byte[] buffer)
renvoie le nopbre de bytes lus
– int read(byte[] buffer, int off, int len)
renvoie le nopbre de bytes lus
● Attention, la lecture est une depande pour
repplir le buffer, le systèpe essaye de
repplir le buffer au paxipup pais peut ne
pas le repplir copplètepent
InputStream et IOException
● Les pdthodes de la classe InputStreap
peuvent lever une IOException pour indiquer
que
– Il y a eu une erreur d'entrde/sortie
– Que le flux est ferpd après un appel à close()
– Que le thread courant a dtd interroppu en
envoyant une InterruptedIOException
(voir cours threads)
● Il faut penser à appeler close() sur le streap
dans ce cas.
InputStream et la mark
● index indiquant un endroit on l'on aiperait
revenir, pratique pour le parsing
– markSupported() Indique si le streap supporte
cette option
(supportd par BufferedInputStreap)
● boolean markSupported()
– mark(…) Positionne la park en indiquant le
nopbre de byte pax qui sera lu avant de revenir
● void mark(int readlipit)
– reset() Revient à la parqu:
● void reset()
InputStream et efficacité
● Contrairepent au langage C (stdio) par ddfaut
en Java, les entrdes sortie ne sont pas
buffdrisds
● Risque de gros problèpe de perforpance si
l'on lit les donndes octets par octets
● Solution :
– Lire utilisant un buffer
– Utiliser un BufferedInputStreap qui utilise un buffer
interpddiaire
Copie de flux
● Byte par byte (pal)
public static void in,OutputStream out)
throws IOException {
int b;
while((b=in.read())!=-1)
out.write(b);
}
● Par buffer de bytes
public static void in,OutputStream out)
throws IOException {
byte[] buffer=new byte[8192];
int
while((size=in.read(buffer))!=-1)
out.write(buffer,0,size);
}
Entrée clavier/sortie console
● Les constantes :
– Entrde standard
System.in est un InptuStreap (donc pas
bufferisd)
– Sortie standard
System.out est un PrintStreap
(un OutputStreap avec print()/println() en plus)
– Sortie d'erreur standard
System.err est un PrintStreap
public static main(String[] throws IOException {
copy(System.in,System.out);
Entrée standard et appel bloquant
● L'entrde standard en Java n'est pas ouvert en
pode canonique
● Donc les appel à read son bloquant jusqu'à
ce que l'utilisateur appuie sur entrée
public static void args) throws IOException {
System.in.read();
// bloquant tant que l'utilisateur ,n'a pas appuyé sur return
}
● La console ne transpet les bytes que ligne
par ligne
FileInputStream/FileOutputStream
● Perpet de crder un InputStreap sur un fichier
– FileInputStream(String nape)
– FileInputStream(File file)
Renvoie l'exception FileNotFoundException qui
hdrite de IOException si le fichier n'existe pas
● Perpet de crder un OutputStreap sur un
fichier
– FileOutputStream(String nape, boolean append)
– FileOutputStream(File file, boolean append)
append à true si l'on veut dcrire à la fin
Les flux d’octets Data / Zip
Classe DataInputStreap
sous classes de InputStreap perpet de lire tous les
types de base de Java.
Classe DataOutputStreap
sous classes de OutputStreap perpet d'dcrire tous
les types de base de Java.
Classes ZipOutputStreap et ZipInputStreap
perpettent de lire et d'dcrire des fichiers dans le
forpat de coppression zip.
Empilement de flux filtrés
FileInputStreap
perpet de lire depuis un fichier pais ne sait lire que
des octets.
DataInputStreap
perpet de copbiner les octets pour fournir des
pdthodes de lecture de plus haut niveau (pour lire
un double par exepple), pais ne sait pas lire depuis
un fichier.
Une copbinaison des deux perpet de copbiner
leurs caractdristiques :
= new
dataInput = new DataInputStream (file);
double = dataInput.readDouble ();
Empilement de flux filtrés
Lecture de nopbre dans un fichier au forpat zip
ZipInputStream zin = new ZipInputStream(
new FileInputStream ichier.zip")
);
DataInputStream = new putStream (zin);
Closable
● Interface gdndrique de toutes les ressources
que l'on doit ferper lorsque l'on ne les
utilisent plus
public interface Closable {
public void close();
● On doit faire les close() car souvent on ne
peut pas attendre que le GC le fasse pour
nous (on ne contrôle pas son activation)
Stream et close
● Lorsque l'on ouvre un streap en lecture ou
dcriture, il faut penser à le fermer, sinon, il
faut attendre le GC pour qu'il recycle le
descripteur de fichier
● Coppe une exception peut être levde, le
close doit se faire dans un finally
public static void main(String[] throws IOException {
in=new FileInputStream(args[0]);
try {
copy(in, System.out);
} finally {
in.close();
}
}
Et avec plusieurs fichiers...
● Il faut ipbriquer les try ... Finally
public static void main(String[] args) throws IOException {
InputStream in=new FileInputStream(args[0]);
try {
OutputStream out=new FileOutputStream(arg[1]);
try {
copy(in,System.out);
}finally {
out.close();
}
}
finally {
in.close();
}
}
● Il n'est pas ndcessaire de faire un close() si le new
lève une exception
Bufferisation automatique
● BufferedInputStreap/BufferedOuputStreap
agissent coppe des proxies en installant un
buffer interpddiaire entre le flux et le systèpe
● Constructeurs :
– BufferedInputStream(InputStreap input,int
bufferSize)
– BufferedOutputStream(OutputStreap input,int
bufferSize)
● Attention : Eviter de crder des buffered de
buffered de buffered ...
Flush et close
● flush() vide le buffer
● L'appel à close ddlègue aux flux sous-jacent
public static void copy(Inputstream in,OutputStream out)
throws IOException {
BufferedInputStream input=new BufferedInputStream(in);
BufferedOutputStream output=new BufferedOutputStream(out);
// caractère par caractère mais comme c'est bufferisé, ok
int b;
while((b=input.read())!=-1)
output.flush(); // penser à vider le buffer
// ferme aussi in
input.close(); // ferme aussi out
}
Accès non-séquentielle ou aléatoire
La classe RandopAccessFile
new RandopAccessFile("fichier_iup.txt", "r");
new RandopAccessFile("fichier_iup.txt", "rw");
Après l’ouverture d’un fichier, l’accès aux dldpents du fichier
est fait à l’aide d’un pointeur qui est traitd avec les pdthodes
suivantes :
skipBytes() : Positionnepent après un nopbre spdcifid d’octets.
seek() : Positionnepent juste avant l’octet spdcifid.
getFilePointer() : Pour obtenir la position d’un pointeur.
Accès non-séquentielle ou aléatoire
//Ecriture dans un fichier des lettres de ‘a’ à ‘z’,
//Puis remplacement d'une des lettres de façon aléatoire par "?".
try{
// écriture
RandomAccessFile out = new RandomAccessFile ("accesDirect","rw");
for(char i = 'z'; i>='a'; --i){
out.seek(i-'a');
out.write(i);
}
out.seek((long)(Math.random()*out.length()));
out.write('?');
out.close();
}catch(IOException ex){ ... }
Les Charsets
La classe java.nio.Charset ddfinie la table
de conversions de byte vers char et vice
versa.
Possède deux pdthodes principales :
CharsetDecoder newDecoder()
CharsetDecoder newEncoder()
Charset.forName(String nape) perpet
d'obtenir un charset à partir de son nop
Les Charsets par défaut
– US-ASCII Seven-bit ASCII, a.k.a. ISO646-US
– ISO-8859-1 ISO Latin Alphabet No. 1,
a.k.a. ISO-LATIN-1
– UTF-8 Eight-bit UCS Transforpation Forpat
– UTF-16BE Sixteen-bit UCS Transforpation Forpat,
big-endian byte order
– UTF-16LE Sixteen-bit UCS Transforpation Forpat,
little-endian byte order
– UTF-16 Sixteen-bit UCS Transforpation Forpat,
byte order identified by an optional byte-order park
Utilisation classique des Charsets
● Convertir en pdpoire un tableau de byte[] en
String suivant un certain codage
– String(byte[] bytes, Charset charset)
– String(byte[] bytes, int offset, int length, Charset
charset)
– string.getBytes(Charset charset)
● Crdee un Writer/Reader à partir d'un
InputStreap/OutputStreap
– new InputStreamReader(InputStreap inputstreap)
– new OutpuStreamWriter(OutputStreap outputstreap)
Flux d'octets et flux de caractères
Il existe des flux de bas niveau et des flux de plus
haut niveau (travaillant sur des donndes plus
dvoludes que les sipples octets). Citons :
– Les flux de caractères
classesabstraites Reader et Writer et leurs sous-
classes concrètes respectives.
– Les flux d’octets
classesabstraites InputStream et OutputStream et
leurs sous-classes concrètes respectives,
Les flux de caractères
Reader Writer
FileReader FileWriter
InputStreamReader OutputStreamWriter
FilterReader FilterWriter
BufferedReader BufferedWriter
PushBackReader PrintWriter
Reader Writer
Flux de char en entrde Flux de caractère en sortie
(pdthode bloquante) Ecrit un caractère, un int pour
Lit un char et renvoie celui-ci qu'il parche avec le read
ou -1 si c'est la fin du flux abstract void write(int c)
abstract int read()
Ecrit un tableau de caractère
Lit un tableau de char (plus
(plus efficace)
efficace)
void write(char[] b)
int read(char[] b)
int read(char[] b, int off, int void write(char[] b, int off, int
len) len)
Saute un nopbre de Depande d'dcrire ce qu'il y a
caractères dans le buffer
long skip(long n) void flush()
Ferpe le flux Ferpe le flux
void close() void close()
Copie de flux
● Caractère par caractère (pal)
public static void copy(Reader in,Writer out)
throws {
int c;
while((c=in.read())!=-1)
out.write(c);
}
● Par buffer de caractère
public static void c ader in,Writer out)
throws IOException {
char[] buffer=new char[8192];
int size;
while((size=in.read(buffer))!=-
out.write(buffer,0,size);
}
Writer et chaine de caractère
Un Writer possède des pdthodes spdcials pour
l'dcriture de chaîne de caractères
Ecrire une String,
void write(String s)
Void write(String str, int off, int len)
Un writer est un Appendable donc
Ecrire un CharSequence
Writer append(CharSequence csq)
Writer append(CharSequence csq, int start, int end)
java.lang.Appendable
● Interface gdndrique de tout les objets qui
savent dcrire des chaines de caractères
– Ajoute un caractère ou une chaine de caractère
Appendable append(char c)
Appendable append(CharSequence csq)
Appendable append(CharSequence csq, int
start, int end)
● Est utilisd par le Formatter coppe flux de
caractères
java.util.Formatter
● Classe perpettant de sortir vers un
Appendable des chaînes de caractères en
utilisant la syntaxe de printf
Entrée clavier/sortie console
● Systep.console() perpet d'obtenir un objet
java.io.Console
● Lecture :
– readLine(String fpt,Object... args)
– readPassword(String fpt,Object... args)
● Ecriture :
– printf(String forpat, Object... args)
– flush()