Abstraction
Abstraction
Un programme intéragie avec le monde extérieur:
- ses actions dépendent des paramètre reçus, des ordres reçus, des événements se produisant pendant son exécution, etc…
- les calculs effectués par le programme servent à déclancher des événements ou sont transmis à l’utilisateur ou à d’autres programmes.
Définition : On appelle Entrées/Sorties (E/S) l’ensemble des actions qui servent respectivement à recevoir et produire des données quel que soit le type d’interaction utilisée.
Types d’interactions
Éditer un fichier Lire un fichier
Envoyer un message Recevoir un message
Ajouter une valeur Consulter une valeur
I/O Stream
Définition : Un flux d’entrée/sortie (I/O Stream en anglais) permet d’encapsuler les envois et les réceptions de données de façon à cacher le support utilisé. Ainsi un même code utilisera indifféremment : un fichier, le réseau ou la mémoire.
Flux de Sortie Flux d’entrée
Ecrire Lire
Les types de flux
Les flux d’entrée/sortie sont des classes permettant d’écrire ou de lire des octets ou des caractères (depuis ou vers une entité quelconque). Ce sont des classes abstraites!!
Input | Output | |
Byte (Octet) | InputStream |
OutputStream |
Character | Reader |
Writer |
OutputStream InputStream
Ecrire des octets Lire des octets
Writer Reader
Ecrire des caractères Lire des caractères
Lecture d’Octets avec InputStream
int read() throws IOException
lecture d’un octet
- bloque jusqu’a ce q’un octet soit disponible
- l’octet lu est retourné sous forme d’un entier
- retourne -1 si la fin du flux est atteinte
void close() throws IOException
: fermeture du flux.
Lecture d’Octets avec InputStream
int read(byte[] b, int off, int len) throws IOException
- bloque jusqu’à ce q’un octet soit disponible
- les octets lus (
len
au maximum) sont placés dans le tableau (a partir de la positionoff
) - retourne le nombre d’octets lus
- retourne -1 si aucun octet n’a été lu et si la fin du flux est atteinte
int read(byte[] b) throws IOException
: identique à read(b, 0, b.length)
Ecriture d’Octets avec OutputStream
void write(int b) throws IOException
: écriture d’un octet
void write(byte[] tab) throws IOException
: écriture d’un tableau d’octets
void flush() throws IOException
: vidage des buffers en forçant l’écriture.
void close() throws IOException
: fermeture du flux.
Exemples
// Récupération du flux
OutputStream os = ?????? ;
// Utilisation du flux
for (byte b=0; b<5 ;b++)
{
os.write(b);
os.write(2*b+1);
}
// Fermeture du flux
os.close();
Exemples
// Récupération du flux
InputStream is = ?????? ;
// Utilisation du flux
int x,y ;
while ((x=is.read())!=-1) {
y = is.read();
dessin.trace(x,y);
}
// Fermeture du flux
is.close();
Lecture de caractères avec Reader
int read() throws IOException
lecture d’un caractère
- bloque jusqu’a ce q’un caractère soit disponible
- le caractère lu est retourné sous forme d’un entier
- retourne -1 si la fin du flux est atteinte
void close() throws IOException
: fermeture du flux.
Lecture de caractères avec Reader
int read(char[] cbuf, int off, int len) throws IOException
- Bloque jusqu’a ce q’un caractère soit disponible
- les caractères lus (
len
au maximum) sont placés dans le tableau (à partir de la positionoff
) - retourne le nombre de caractères lus
- retourne -1 si aucun caractère n’a été lu et si la fin du flux est atteinte
int read(char[] cbuf) throws IOException
: identique à read(cbuf, 0, cbuf.length)
Ecriture de caractères avec Writer
void write(int b) throws IOException
: écriture d’un caractère
void write(char[] cbuf) throws IOException
: écriture d’un tableau de caractères
void write(String str) throws IOException
: écriture d’une chaine de caractères
void flush() throws IOException
: vidage des buffers en forçant l’écriture.
void close() throws IOException
: fermeture du flux.
Exemples
// Récupération d’un flux
Writer w = ?????? ;
// Utilisation du flux
w.write('a');
w.write('b');
w.write("cdef");
// Fermeture du flux
w.close();
Exemples
// Récupération d’un flux
Reader r = ?????? ;
// Utilisation du flux
StringBuffer buff = new StringBuffer();
int i;
while ((i=r.read())!=-1) {
buff.append((char)i);
}
// Fermeture du flux
r.close();
Construction de Flux d’E/S
Où sont les flux?
On distingue deux méthodes pour obtenir la référence d’un flux :
- Par accesseur : certaines classes de Java possèdent des flux pour produire ou recevoir des données. Ceux-ci sont accessibles directement (
System.in
etSystem.out
) ou au travers d’accesseurs (getInputStream()
etgetOutputStream()
). - Par constructeur : pour les objets qui ne possèdent pas directement de flux, Java offre pour les construire des classes spécifiques à chaque support. Toutes ces classes héritent d’un des 4 flux de base :
InputStream
,OutputStream
,Reader
ouWriter
.
Flux standard
La classe System est pourvue de trois attributs de classe :
in
: un flux qui correspond à l’entrée standard (par défaut le clavier)out
: un flux qui correspond à la sortie standard (par défaut la console)err
: un flux qui correspond à la sortie d’erreur (par défaut la console)
// Lecture sur le clavier
int x = System.in.read();
// Écriture sur la console
System.out.write(x);
Flux standard
Dans le cas de la classe Process
les flux permettent d’écrire (resp. de lire) sur l’entrée standard (resp. la sortie standard) du processus.
// Lancement du programme say (Mac Os)
Process p = Runtime.getRuntime().exec("say");
// Récupération du flux d’entrée standard du programme
// ATTENTION : Pour nous c’est un flux de sortie (out)
OutputStream os = p.getOutputStream();
// Utilisation du flux : comme avec tout OutputStream
os.write("bonjour, comment ça va?".getBytes());
// Fermeture du flux (=> arrêt du programme beep)
os.close();
Construction de flux
Source / Destination (Défini avec un préfixe) |
Entrée en Octets (Hérite de InputStream) |
Sortie en Octets (Hérite de OutputStream) |
Tableau d’octets en mémoire | ByteArrayInputStream | ByteArrayOutputStream |
Fichier | FileInputStream | FileOutputStream |
Pipeline entre deux threads | PipedInputStream | PipedOutputStream |
Chaîne de caractères | StringBufferInputStream | StringBufferOutputStream |
Construction de flux
Source / Destination (Défini avec un préfixe) |
Entrée en caractères (Hérite de Reader) |
Sortie en caractères (Hérite de Writer) |
Tableau d’octets en mémoire | CharArrayReader | CharArrayWriter |
Fichier | FileReader | FileWriter |
Pipeline entre deux threads | PipedReader | PipedWriter |
Chaîne de caractères | StringReader | StringWriter |
Exemples
// Récupération du flux
OutputStream os = new FileOutputStream("/path/to/file.bin");
// Utilisation du flux
for (byte b=0; b<5 ;b++)
{
os.write(b);
os.write(2*b+1);
}
// Fermeture du flux
os.close();
// Récupération du flux
InputStream is = new FileInputStream("/path/to/file.bin");
// Utilisation du flux
int x,y ;
while ((x=is.read())!=-1) {
y = is.read();
dessin.trace(x,y);
}
// Fermeture du flux
is.close();
Exemples
// Recupération d’un flux
Writer w = new FileWriter("/path/to/file.txt"); ;
// Utilisation du flux
w.write('a');
w.write('b');
w.write("cdef");
// Fermeture du flux
w.close();
// Récupération d’un flux
Reader r = new FileReader("/path/to/file.txt");
// Utilisation du flux
StringBuffer buff = new StringBuffer();
int i;
while ((i=r.read())!=-1) {
buff.append((char)i);
}
// Fermeture du flux
r.close();
Les filtres
Les filtres
Définition : Pour ajouter des fonctionnalités aux flux, Java utilise des classes appelées filtre suivant le patron de conception (design-pattern) du décorateur.
Le nom des filtres Java est suffixé par l’un des quatre flux de base :
- ils héritent de
Filter[FluxBase]
qui hérite de[FluxBase]
- ils prennent ce flux comme paramètre de leur constructeur.
Pour ajouter des fonctionnalités ils peuvent :
- redéfinir le fonctionnement des méthodes de base (read, write, …), par polymorphisme l’utilisation est transparente et interchangeable
- ajouter de nouvelles méthodes (print, writeBoolean, readLine, …)
Les filtres
Préfixe | Fonctionnalité |
InputStream |
OutputStream |
Reader |
Writer |
Buffered |
Mise en tampon | ||||
Data |
Conversion des types primitifs | ||||
Object |
Sérialisation d’objet | ||||
Sequence |
Concaténation de flux | ||||
Print |
Fonctions de formatage print |
||||
PushBack |
Lecture avec remise dans le flux | ||||
LineNumber |
Numérotation des lignes | ||||
Digest |
Vérification par somme de contrôle | ||||
Cipher |
Chiffrage du flux |
Attention
InputStreamReader
, resp. OutputStreamWriter
n’est pas un flux de type InputStream
, resp. OutputStream
.
C’est un constructeur de flux de type Reader
, resp. Writer
, à partir d’un flux de type InputStream
, resp. OutputStream
Compositions de filtres
OutputStream |
InputStream |
OutputStream os = ?????? ;
os.write((byte)1);
os.write((byte)2);
os.write((byte)3);
os.close();
InputStream is = ?????? ;
while ( (x = is.read()) != -1 )
{
System.out.println(x);
}
is.close();
FileOutputStream |
FileInputStream |
OutputStream os =
new FileOutputStream("test.bin");
os.write((byte)1);
os.write((byte)2);
os.write((byte)3);
os.close();
InputStream is =
new FileInputStream("test.bin");
while ( (x = is.read()) != -1 )
{
System.out.println(x);
}
is.close();
CipherOutputStream |
FileOutputStream |
FileInputStream |
CipherInputStream |
OutputStream os =
new CipherOutputStream(
new FileOutputStream("test.bin"),c);
os.write((byte)1);
os.write((byte)2);
os.write((byte)3);
os.close();
InputStream is =
new CipherInputStream(
new FileInputStream("test.bin"), c);
while ( (x = is.read()) != -1 )
{
System.out.println(x);
}
is.close();
GZIPOutputStream |
CipherOutputStream |
FileOutputStream |
FileInputStream |
CipherInputStream |
GZIPInputStream |
OutputStream os =
new GZIPOutputStream(
new CipherOutputStream(
new FileOutputStream("test.bin"),c)
);
os.write((byte)1);
os.write((byte)2);
os.write((byte)3);
os.close();
InputStream is =
new GZIPInputStream(
new CipherInputStream(
new FileInputStream("test.bin"), c)
);
while ( (x = is.read()) != -1 )
{
System.out.println(x);
}
is.close();
Filtres personnalisés
Pour un filtre personnalisé destiné à la lecture d’octets : définir une classe qui hérite de FilterInputStream
, implémenter un constructeur à un paramètre InputStream is
:
- appeler à la première ligne du constructeur
super(is)
- si besoin enregistrer les autres paramètres dans des attributs
redéfinir la méthode read()
:
- utiliser
super.read()
pour obtenir la valeur avant transformation - appliquer le filtre
- retourner la valeur modifiée
Exemple
import java.io.*;
class DoubleReader extends FilterReader {
private int lastChar = -1;
public DoubleReader(Reader r) {
super(r);
}
@Override
public int read() throws IOException {
if(lastChar != -1) {
int r = lastChar;
lastChar = -1;
return r;
}
lastChar = super.read();
return lastChar;
}
}
Nouvelles API java.nio.file
java.nio.file
API
Java 8 introduit de nouvelles API pour la lecture de fichiers
Files
est une classe contenant des méthodes statiques pour manipuler les fichiers et les dossiers.
Fonction pour la lecture
Files.newBufferedReader(Path p )
: Obtenir un buffer reader du fichier localisé au cheminp
Files.lines(Path p)
: Obtenir unStream
contenant les lignes du fichier localisé au cheminp