• Aucun résultat trouvé

Les applications ont très souvent besoin d’accéder à des ressources externes, qui fournissent ou reçoivent des données de l’application (donc transite ou transfert de données), comme :

N/A
N/A
Protected

Academic year: 2022

Partager "Les applications ont très souvent besoin d’accéder à des ressources externes, qui fournissent ou reçoivent des données de l’application (donc transite ou transfert de données), comme : "

Copied!
474
0
0

Texte intégral

(1)

M. AFILAL

Java_Avancé

2019-2020

(2)

M.AFILAL 2

Introduction et principe de E /S

Les applications ont très souvent besoin d’accéder à des ressources externes, qui fournissent ou reçoivent des données de l’application (donc transite ou transfert de données), comme :

– fichiers, mémoire, les pipes.

Le transfert de données, entre des applications ou entre application et des ressources externes, est appelé flux (stream en anglais) de données.

– Un flux est en quelque sorte un canal dans lequel de l'information transite.

Manipuler un flux, pour tout type de flux, c’est : Ouverture du flux,

Ecriture ou lecture des données dans le flux,

Fermeture du flux.

(3)

M.AFILAL 3

Introduction et principe de E /S

Les fichiers:

– se sont des fichiers localisés sur disque dure La mémoire:

– se sont des variables représentant:

des caractères,

des tableaux de caractères, des bytes ou tableaux de bytes, des String

des StringBuffer Les pipes:

– se sont des canaux qui permettent de :

communiquer des informations entre deux programmes (ou deux

«threads») qui s’exécutent concurremment (notion de synchronisation)

transiter des données à travers le réseau

(4)

M.AFILAL 4

Introduction et principe de E /S

Java fournit des classes qui représentent les flux et permettent leur manipulation, l’ensemble de ses classes constitue le package java.io (la bibliothèque des E/S).

– Certains types de flux agissent sur la façon dont sont traitées les données qui transitent par leur intermédiaire :

E/S bufférisées, traduction de données (d’un codage à autre par exemple),

– Pour réaliser la gestion souhaitée pour les E / S, on peut combiner différents types de flux.

– Généralement,

Si le flux provient d’une source extérieure (clavier, fichier...) vers le programme: on parle alors de flux en lecture.

Si le flux vient du programme et écrit dans un fichier, à l’écran ou autre... : on parle alors de flux en écriture.

le package java.io prend en charge de nombreux type de sources de données et

d’opérations sur ces données.

(5)

M.AFILAL 5

Introduction et principe de E /S

L’information lue ou écrite est représentée par un flux de données, deux types d’objets sont utilisés dans ce but :

– Un flux physique,

il prend en charge le type de la source de données.

– Il sait, par exemple, comment lire le contenu d’un fichier.

– Un filtre,

il prend en charge la manière de gérer le flux:

– la manière de lire ou d’écrire les données.

Par exemple, pour optimiser la lecture.

Remarque:

– Un filtre ne sait pas accéder à une source physique (fichier, mémoire, pipe),

il s’appuie sur un objet de type flux physique.

(6)

M.AFILAL 6

Introduction et principe de E /S

Application

Lecture du flux Transmet le flux Filtre de lecture

Flux physique

Source de données

Retransmet le flux

Écriture du flux

Filtre d’écriture

Flux physique

Destination de données

(7)

M.AFILAL 7

Introduction et principe des E / S

La bibliothèque des E\S propose quatre hiérarchies de classes (des classes de flux) qui permettent où qui dérivent des postulas suivants :

Des accès en mode binaire (lecture ou écriture octet par octet : 8 bits)

Des accès en mode texte (ou mode caractère, un caractère unicode: 16 bits en java).

Des flux de lecture et des flux d’écriture sont différenciés.

Des classes complémentaires permettent de :

Récupérer des informations (droit d’accès, etc. …) sur un fichier.

Gérer les fichiers en accès direct ou indirecte.

Prendre en charge les erreurs de lecture / écriture.

(8)

M.AFILAL 8

Introduction et principe de E /S

(9)

M.AFILAL 9

Introduction et principe de E /S

InputStream :

– Classe qui gère le flux d’entrée « accès séquentiel en mode binaire en lecture (mode octet) ».

OutputStream :

– Classe qui gère le flux de sortie « accès séquentiel en mode binaire en écriture (mode octet) ».

Reader :

– Classe qui permet un accès en lecture « accès séquentiel en lecture en mode caractère ».

Writer :

– Classe qui permet un accès en écriture « accès séquentiel en écriture en mode caractère ».

RondomAccessFile :

– Classe qui permet un accès directe (lecture/écriture) aux données dans un fichier.

Elle permet de lire ou d'écrire tous les types Java de base, les lignes, les

chaînes de caractères ascii ou unicode, etc ...

(10)

M.AFILAL 10

Règles pour les flux des E /S

Pour accéder à une source de données, il faut déterminer : Le type de gestion :

– accès directe, lecture séquentielle ou écriture séquentielle, L’accès :

– mode binaire ou mode caractère.

Le type de la source de données : – fichier, mémoire, pipe:

disque dure, console, écran, etc.…., La manière de gérer le flux :

– choisir le filtre adéquat (peut être aucun).

(11)

M.AFILAL 11

Partie I

Partie I

(12)

M.AFILAL 12

Manipulations des fichiers indépendamment des données

Comment manipuler des fichiers Indépendamment des données qu'ils contiennent, tels que : – le renommage, la suppression,

– connaître les droits d'un fichier en terme de sécurité, …..

Pour cela, on utilise la classe File du package java.io, – elle permet de manipuler un fichier sur le disque dur.

Quelques méthodes de la classe File.

– public File (String pathname)

Crée un nouvel objet File, correspondant au chemin (path) indiqué. Par exemple, avec

– File f = new File("C\\FichierJava");

– f désignera le répertoire "C\\FichierJava ". Le chemin peut correspondre à un fichier ou à un répertoire.

– public File (File parent, String child)

Crée un nouvel objet File, correspondant au chemin (path) composé en ajoutant child à parent. Ainsi, en exécutant le code :

– File homedir = new File("/home/java");

– File f = new File(homedir, "MonProg.java");

– f désignera le fichier "/home/java/MonProg.java".

– long lastModified ( ): retourne la date de la dernière modification.

– boolean setReadOnly ( ) : place un fichier en lecture seule.

(13)

M.AFILAL 13

Quelques méthodes de la classe File

(14)

M.AFILAL 14

Exemple: classe GestionFile

import java.io.File;

public class GestionFile { – public GestionFile() { }

– // Méthode permettant l'affichage des caractéristiques d'un fichier s’il existe.

– void getFile(String nomFile) { File f = new File(nomFile);

System.out.println(f.getAbsolutePath() + " :: " + f.getName());

if (f.exists()) {

– System.out.println(f.getName() + " : " + (f.canRead() ? "r" : "-") + (f.canWrite() ? "w" : "-") + " :: " + f.length());

– f.delete(); // attention }

else {

– System.out.println("fichier non existant ");

} – }

(15)

M.AFILAL 15

Exemple: classe GestionFile

// Méthode permettant de lister l'ensemble de fichier ou directory qui se trouve dans nomDossier si c'est un dossier si non affichage du fichier nomDossier.

– void typeDossier(String nomDossier) { try {

– File f = new File(nomDossier);

– String[ ] files = f.list();

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

if (new File(nomDossier + "\\" + files[i]).isDirectory()) {

System.out.println("Rep : " + nomDossier + "\\" + files[i]);

typeDossier(nomDossier + "\\" + files[i]);

} else {

System.out.println("Fil : " + nomDossier + "\\" + files[i]);

getFile(nomDossier + "\\" + files[i]);

} – }

}catch (NullPointerException e) {

– System.out.println("le type du dossier entrée est un fichier ou répertoire introuvable");

}finally {

– getFile(nomDossier);

} – } }

(16)

M.AFILAL 16

Partie II

Partie II

(17)

M.AFILAL 17

L’accès séquentiel en mode binaire(ou mode octet)

Utiliser cet accès pour des données binaires séquentielles (image, chansons,…..).

– Seuls les caractères codés selon l’ISO Latin1 (ISO-8859-1) sont pris en compte :

– Les caractères lus dans la source doivent avoir été encodés avec l’ISO Latin-1

– Les caractères écrits dans le flux seront encodés avec l’ISO Latin-1 – Pour accéder à la source de données, il faut déterminer :

– L’accès en lecture ou écriture

– Le type de la source de données : fichier, mémoire, etc.….

– La manière de gérer le flux : choisir le filtre adéquat (peut être aucun) Remarque:

– ISO Latin1: Code ASCII étendu à 8 bits comprenant tous les caractères accentués de la langue française.

– Les flux d’octets (binaire) permettent de lire et écrire une suite d’octets (sans aucune conversion, rapide mais non compréhensible par l’utilisateur)

– Les flux de caractères permettent de lire et d’écrire une suite de caractères

(avec conversions éventuelles « utilisation d’un nouveau encadage », pas très

rapide mais compréhensible par l’utilisateur).

(18)

M.AFILAL 18

Accès séquentiel binaire en lecture

Les flux physiques en mode binaire:

– La classe abstraite InputStream:

est le modèle de base pour toutes les classes flux physiques pour une lecture séquentielle binaire.

– On ne peut pas utiliser directement la classe InputStream car:

elle ne propose que des méthodes élémentaires de récupération de données,

elle n’implante pas la méthode read( ) qui doit être définie par toutes les classes dérivées.

– La fonction read( ): retourne un int.

À chaque appel de cette méthode,

– on se déplace d’un octet sur le flux,

– retourne la valeur -1 si on atteint la fin du flux.

Elle permet de lire un byte ou un tableau de byte – La fonction read( byte[ ] buffer): retourne un int

Elle permet de lire un tableau d’octets, de taille du tableau buffer, depuis le flux.

Elle retourne le nombre d’octets lus.

Elle lit autant d’octets qu’elle peut en stocker dans le tableau et autant qu’elle peut en lire sur le flux.

Elle retourne -1 si la lecture à échoué (fin du flux).

(19)

M.AFILAL 19

Accès séquentiel binaire en lecture

Principe d’utilisation des flux en mode binaire :

– Pour la lecture :

Création de l’objet d’un type héritant d’InputStream Invocation de la méthode read

Fermeture par la méthode close

– Pour l’écriture :

Création de l’objet d’un type héritant d’OutputStream Invocation de la méthode write

Fermeture par la méthode close

(20)

M.AFILAL 20

Les flux physiques

(21)

M.AFILAL 21

Les flux physiques

ByteArrayInputStream :

– Permet de lire une zone mémoire (un tableau d’octets).

FileInputStream :

– Permet la lecture des données contenues dans un fichier byte par byte.

ObjectInputStream :

– Elle possède différentes méthodes pour lire tout type de données (primitifs ou objets).

PipedInputStream :

– Lecture de bytes dans un canal de communication entre deux applications.

– Utilisée dans la communications via les réseaux et les gestions des processus légers (les threads).

Permet de faire communiquer deux thread (processus légers)

Tout ce qui est écrit dans un tube par thread est lu dans l’ordre par l’autre thread SequenceInputStream :

– Représente la concaténation de plusieurs flux de lecture en un seul.

– Lorsqu’on atteint la fin d’un flux, la lecture continue sur le flux suivant.

StringBufferInputStream :

– Lecture de bytes depuis un string (la source est traitée comme un string, une chaîne de caractères).

– Cette classe et l’ensemble de ses méthodes sont dépréciées car convertissent mal les caractères en octets (bytes).

(22)

M.AFILAL 22

Les filtres pour accès séquentiel binaire en lecture

(23)

M.AFILAL 23

Les filtres: pour accès séquentiel binaire en lecture

Un filtre, en lecture binaire :

– s’appuie sur un objet de type InputStream qui lui transmet le flux.

Le filtre peut alors le transformer ou effectuer toute autre opération et retransmet à son tour le flux.

la classe BufferedInputStream :

– Permet d’utiliser un buffer pour accélérer la lecture, la classe DataInputStream :

– Permet de lire des bytes d’un flux binaire et les transformer en données Java de type primitif.

– Permet de lire, de manière indépendante de la plate forme,

Un flux contenant des données ayant un type primitif Java (int, float, double …), Un flux représentant des chaînes de caractères au format Unicode,

PushbackInputStream :

– Cette classe ajoute la possibilité de revenir en arrière dans un flux.

Remarque:

– On ne doit plus utiliser readLine() de DataInputStream (ceci recevant un message de dépréciation au moment de la compilation), mais on utilise à la place un BufferedReader.

(24)

M.AFILAL 24

Exemple_1

public void copie1(String source) throws IOException { – FileInputStream is = null;

– try{

is = new FileInputStream(source);

int c;

int nbOctet = is.available();

long saut = is.skip(2);

System.out.println("nombre d’otets lu est égale à: " + nbOctet + " saut = " + saut);

– // la fonction read retourne l'octet lu et lève l’exception IOException while ( (c = is.read( )) != -1) {

– System.out.println("l’octet lu et le caractère correspondant sont: " + c + " " + (char) c);

}

– }catch(NullPointerException e){ System.out.println("Fichier introuvable.");

– }finally{ if (is != null) is.close(); }

} // voir classe LectureEcritureBinaireFichier_New Remarque

– available( ):

Méthode qui retourne une estimation du nombre d'octets qu'il est encore possible de lire dans le flux

– skip( long ):

saute autant d'octets dans le flux que la valeur fournie en paramètre. Elle renvoie le nombre d'octets sautés, , ici = 2, donc, on commence la lecture à partir du troisième octet.

(25)

M.AFILAL 25

En Java, chaque type de flux est destiné à réaliser une tâche.

– Lorsque le programmeur souhaite un flux qui ait un comportement plus complexe

"empile", à la façon des poupées russes, plusieurs flux ayant des comportements plus élémentaires.

– On parle de flux filtrés.

Concrètement, il s'agit de passer, dans le constructeur d'un flux, un autre flux déjà existant pour combiner leurs caractéristiques.

Exemple:

– Une combinaison des deux classes:

FileInputStream (elle ne sait lire que des octets se trouvant dans un fichier) et

DataInputStream (elle ne sait pas lire depuis un fichier mais elle sait lire les types primitifs de java)

– permet de combiner leurs caractéristiques :

FileInputStream fic = new FileInputStream ("fichier");

DataInputStream din = new DataInputStream (fic);

double d = din.readDouble ( );

Remarque: Empilement de flux filtrés

(26)

M.AFILAL 26

Lecture bufférisée d’un nombre depuis un fichier

– DataInputStream din = new DataInputStream (new BufferedInputStream (new FileInputStream ("monfichier")));

– double d = din.readDouble ( );

Lecture de nombre dans un fichier au format zip

– ZipInputStream zin = new ZipInputStream ( new FileInputStream ("monfichier.zip"));

– DataInputStream din = new DataInputStream (zin);

– double b = din.readDouble ( );

Remarque

– ZipInputStream est un filtre qui est une sous classe de FilterInputStream

Remarque: Empilement de flux filtrés

(27)

M.AFILAL 27

Exemple _2

public void lectureParBloc(int dimBloc) { FileInputStream fis = null;

byte[ ] buffer = new byte[dimBloc];

int i = 0; // compteur de nombre byte lus depuis le flux try {

File fichier = new File("E:/Documents and

Settings/Administrateur/Bureau/Dossier1mm.mp3");

fis = new FileInputStream(fichier);

Calendar calDeb = Calendar.getInstance();

// création d'un objet de type Calendar avec des valeurs de date et heures système avant début de la lecture

for (int j = 0; j < 3000; j++) {

// création d'un objet de type string avec le tableau de byte buffer String s = new String(buffer);

// affichage de la chaîne de caractère lu dans le tableau buffer System.out.println("chaîne de caractère lu dans l'itération " + j + " est: " + s);

i += fis.read(buffer);

}

Calendar calFin = Calendar.getInstance(); // temps après fin de la lecture System.out.println( i );

System.out.println("temps de lecture en ms = " + (calFin.getTimeInMillis() - calDeb.getTimeInMillis( ) ) );

}catch (FileNotFoundException e) { System.out.println("Fichier non trouvé1");

}catch (IOException e) { System.out.println("Impossible de lire");

} finally {

if (fis != null) {

try { fis.close(); // fermeture du flux }

catch (IOException e) { System.err.println("problème dans la fermeture du flux"); } }

} }

(28)

M.AFILAL 28

Exemple _3

public void lectureParBlocBuffered(int dimBloc) { byte[ ] buffer = new byte[dimBloc];

BufferedInputStream fis = null;

int i = 0; // affichage de nombre total de byte lu dans le flux try {

// accès au fichier via un Buffer donc lecture plus rapide

fis = new BufferedInputStream(new FileInputStream("C:/Documents and Settings/Administrateur/Bureau/dossier1/chanson.mp3"));

Calendar calDeb = Calendar.getInstance();

for (int j = 0; j < 3000; j++) {

String s = new String(buffer);

System.out.println(s);

i += fis.read(buffer);

}

Calendar calFin = Calendar.getInstance();

System.out.println( i );

System.out.println("temps de lecture en ms = " + (calFin.getTimeInMillis() - calDeb.getTimeInMillis()));

}catch (FileNotFoundException e) { System.out.println("Fichier non trouvé.");

}catch (IOException e) { System.out.println("Impossible de lire");

} finally {

if ( fis != null ) {

try { fis.close(); // fermeture du flux }

catch (IOException e) { System.out.println("problème dans la fermeture du flux"); } }

}

} // voir classe LectureEcritureBinaireFichier_New avec le bloc « try-with-resource »

(29)

M.AFILAL 29

Exemple _4

public void lectureBufferedTypee(String nomFichier) { – DataInputStream dis = null;

– try {

File fich = new File(nomFichier);

FileInputStream fis = new FileInputStream(fich);

BufferedInputStream bis = new BufferedInputStream(fis);

– //classe permettant de lire tous les types de base de Java dis = new DataInputStream(bis);

int a = dis.readInt( );

short s = dis.readShort( );

boolean b = dis.readBoolean( );

String st = dis.readUTF( );

System.out.println("affichage types primitifs:" + a + " " + s + " " + b + " " + st);

– }catch (NullPointerException e) {

System.err.println("Fichier non trouvé");

– }catch (FileNotFoundException e) {

System.err.println("Fichier non trouvé");

– }catch (IOException e) {

System.err.println("Impossible de lire4");

– }finally{

if (dis != null) dis.close( );

– } }

(30)

M.AFILAL 30

L’instruction "try-with-resource"

Remarque:

– L’instruction "try-with-resource" de Java 7 permet de gérer automatiquement la fermeture des ressources (fichiers , flux, readers, writers, sockets, connexions …).

Ceci permet d’éviter d’utiliser le bloc "finally" et surtout d’éviter les bugs liés aux oublis d’appels de la méthode "close()" !

public static void main(String args[ ]) {

– String filepath = "src/demo/trywithresource/mytext.txt";

– try (BufferedReader reader = new BufferedReader(new FileReader(filepath))) {

String line = reader.readLine();

while (line != null) { System.out.println(line); line = reader.readLine( );}

– }

– catch (IOException e) { System.err.println("Erreur : " + e.getMessage()); } }

– Une ressource est un objet qui doit être fermé lorsque l'on a plus besoin de lui.

– le mot clé try peut être utilisé pour déclarer une ou plusieurs ressources.

– le "try-with-resource" fonctionne avec les classes implémentant l’interface

"java.lang.AutoClosable". Cette interface a été définie pour indiquer qu'une ressource peut être fermée automatiquement.

– L'interface java.io.Closable hérite de l'interface AutoCloseable : ainsi toutes les classes qui implémentent l'interface Closable peuvent être utilisées comme ressource dans une instruction try-with-resource.

(31)

M.AFILAL 31

L’instruction "try-with-resource"

Remarque:

– S’il ya plusieurs ressources alors elles sont séparées par un ;.

– Si, on ne veut pas faire la déclaration d’une ressource dans l’instruction try, alors on peut définir une variable et de l'initialiser avec l'instance existante.

public void Teste( ) {

– String filepath = "src/demo/trywithresource/mytext.txt";

– BufferedReader reader = new BufferedReader(new FileReader(filepath));

– try (BufferedReader closeableReader = reader ) { String line = reader.readLine();

while (line != null) { System.out.println(line); line = reader.readLine( );}

– }

– catch (IOException e) { System.err.println("Erreur : " + e.getMessage()); } – // …. Autre code qui dépend de reader …… dans finally par exemple

}

Dans l'exemple ci-dessus, comme la variable définie et celle existante pointent sur la même référence, les deux variables peuvent être utilisées indifféremment. L'instruction try-with- resource se charge de fermer automatiquement le flux.

Attention, seules les ressources déclarées dans l'instruction try seront fermées

automatiquement. Si une ressource est explicitement instanciée dans le bloc try, la gestion de la fermeture et de l'exception qu'elle peut lever doit être gérée par le développeur.

(32)

M.AFILAL 32

Accès séquentiel binaire en écriture

Les flux physiques

La classe abstraite OutputStream:

– C’est le modèle de base pour toutes les classes flux physiques pour écriture binaire séquentielle.

– C’est la super classe de toutes celles représentant un flux de sortie d’octets

Elle n’implante pas la méthode write( int)

– Cette méthode doit être définie par toutes les classes dérivées.

– Cette méthode permet d’écrire un byte ou un tableau de byte

– Prenant en paramètre un octet (bien qu’il est contenu dans un int) à

écrire sur le flux de sortie.

(33)

M.AFILAL 33

Accès séquentiel binaire en écriture

write(int b):

– prenant en paramètre un octet (bien que contenu dans un int) à écrire sur le flux de sortie.

La classe fournit également d’autres méthodes : – void write(byte[ ] b) :

cette méthode permet d’écrire plus d’un octet à la fois. En effet, les octets stockés dans le tableau passé en paramètre seront tous écrits en un seul appel de cette méthode.

– void write(byte[ ] b, int off, int len) :

cette méthode permet d’écrire sur le flux l’intégralité du tableau, on

commence à écrire les octets à partir de la position off (offset) du tableau.

Le paramètre len correspond au nombre d’octets à écrire.

– close( ) :

Cette méthode permet de fermer le flux. Cette méthode doit toujours être appelée quand on a fini d’écrire sur le flux.

– flush( ) :

Cette méthode permet de vider le buffer et force l’écriture des données

dans le flux. (Demande d'écrire dans le flux ce qu'il y a dans le buffer).

(34)

M.AFILAL 34

Accès séquentiel binaire en écriture

(35)

M.AFILAL 35

Accès séquentiel binaire en écriture

FileOutputStream :

– Permet l’écriture de données dans un fichier dont le nom est donné dans le constructeur.

– Il est possible de spécifier dans le constructeur si le contenu doit s’ajouter à la suite du contenu existant ou écraser les valeurs précédentes (si le fichier

existait déjà).

Par défaut, le contenu sera remplacé.

ByteArrayOutputStream :

– Implémente un flux de sortie dans lequel les données sont écrites dans un

tableau de byte. Le buffer augmente au fur et à mesure que des données sont

écrites.

(36)

M.AFILAL 36

Les filtres pour accès séquentiel binaire en écriture

La classe PrintStream:

– Permet d’écrire des caractères, des types primitifs, des textes et aussi des objets sérialisés (la sérialisation est un mécanisme de stockage des objets)

– Permet d’écrire dans le flux la conversion des types primitifs en chaîne de caractères.

– Java utilise cette classe pour les affichages sur écrans (System.out est de type PrintStream).

– Elle permet également de contrôler le vidage du tampon (flush).

– Les méthodes de ce flux ne lèvent aucune exception en cas d’erreurs (le

programmeur doit gérer les exceptions lui même pour vérifier si l’opération

d’écriture s’est bien déroulée ou pas).

(37)

M.AFILAL 37

Les filtres pour accès séquentiel binaire en écriture

Un filtre pour les accès en écriture s’appuie sur un objet de type OutputStream qui récupère le contenu du flux :

Le filtre traite les données du flux puis les retransmets à l’objet flux associé.

– La classe BufferedOutputStream:

Permet d’utiliser un buffer pour accélérer l’écriture.

– La classe DataOutputStream:

Fonctionne comme DataInputStream mais en écriture.

– Permet de convertir des valeurs de type primitif en flux binaire Fournit des méthodes pour écrire des données sous formes de types primitifs Java, dans un flux de sortie, de manière portable.

– Donc, elle permet d'écrire tous les types de base de Java.

Ainsi, elles pourront être récupérées par la suite via un flux d’entrée:

DataInputStream.

– La classe DataOutputStream et la classe DataInputStream doivent être utilisées

en association pour lire un flux écrit par l’autre.

(38)

M.AFILAL 38

Exemple : lecture et écriture par bloc

public void CopieFichierBinaire(String FichierEntree, String FichierSortie) throws IOException {

final int BufSize = 4096; // lecture par bloc de taille 4096 octets String input = FichierEntree; // fichier à lire

String output = FichierSortie; // fichier où on va stocker les données lues FileInputStream in = new FileInputStream(input);

FileOutputStream out = new FileOutputStream(output);

int nb; // nombre d’octets lus

// Tableau qui contiendra les byte ou les octets lus dans le fichier input byte[] buf = new byte[BufSize];

while ( (nb = in.read(buf)) != -1) { out.write(buf);

}

in.close();

out.close();

}

public void CopieFichierBinaire(String FichierEntree, String FichierSortie) throws IOException {

final int BufSize = 4096; // lecture par bloc de taille 4096 octets String input = FichierEntree; // fichier à lire

String output = FichierSortie; // fichier où on va stocker les données lues FileInputStream in = new FileInputStream(input);

FileOutputStream out = new FileOutputStream(output);

int nb; // nombre d’octets lus

// Tableau qui contiendra les byte ou les octets lus dans le fichier input byte[] buf = new byte[BufSize];

while ( (nb = in.read(buf)) != -1) { out.write(buf);

}

in.close();

out.close();

}

Méthode permettant de copier, avec format lecture binaire, le contenu d'un fichier et le mettre, avec format d'écriture binaire, dans un autre fichier

.

(39)

M.AFILAL 39

Exemple _1: lecture et écriture byte par byte

public void copie2(String source, String dest) throws IOException { – FileInputStream is = new FileInputStream(source);

– FileOutputStream os = new FileOutputStream(dest);

– int c;

– while ( (c = is.read()) != -1) {

System.out.println("le byte lu et le caractère correspondant sont: " + c + " " + (char) c);

os.write( (byte) c);

– }

– os.close();

– is.close();

}

(40)

M.AFILAL 40

Exemple _2

Méthode permettant d'écrire, sous format binaire, un texte à la fin d'un fichier, jusqu'a entrée , via le clavier, d’un string de taille nulle. Elle retourne une exception de type IOException public void copieEcriture1(String dest) throws IOException {

– FileOutputStream os = null;

– try {

os = new FileOutputStream(dest, true);

while (true) {

– String str = (new DataInputStream(System.in)).readLine();

– if(str.equals("")) break;

– os.write(str.getBytes( )); // écriture de bloc de byte }

– }catch (NullPointerException e) {

System.out.println("Fichier introuvable.");

– }

– finally {

if (os != null) os.close( );

– } }

Remarque:

– System.in est un objet de type inputStream, permet de lire les entrées clavier sous format binaire

– La méthode readLine retourne un string

(41)

M.AFILAL 41

Exemple _3

Méthode permettant d'écrire dans un fichier en utilisant la classe PrintStream avec association d'un buffer, ce qui permet une conversion des types primitif en format string.

public void ecritureAvecPrintStream(String nomFichier) { – File fich = new File(nomFichier);

– int a = 10;

– char s = 'y';

– boolean b = true;

– try {

FileOutputStream fos = new FileOutputStream(fich, true);

BufferedOutputStream bos = new BufferedOutputStream(fos);

PrintStream dos = new PrintStream(bos);

dos.println(a);

dos.println(s);

dos.println(b);

dos.println("le code est simple avec printStream");

dos.close( );

– }catch (FileNotFoundException e) {

System.out.println("Fichier non trouvé");

– }catch (IOException e) {

System.out.println("Impossible d’écrire dans le fichier");

– } }

(42)

M.AFILAL 42

Exemple _4

public void ecritureParBlocBufferedTypee(String nomFichier) { File fich = new File(nomFichier);

DataOutputStream dos = null;

int a = 10;

short s = 3;

boolean b = true;

try {

FileOutputStream fos = new FileOutputStream(fich, true);

BufferedOutputStream bos = new BufferedOutputStream(fos);

dos = new DataOutputStream(bos);

System.out.println("nombre de bytes écrits, au début, dans le flux est " + dos.size());

dos.writeInt(a);

dos.writeShort(s);

dos.writeBoolean(b);

dos.writeUTF("le code est simple");

System.out.println("nombre de bytes écrits dans le flux est: " + dos.size());

dos.flush(); // vide le tampon

}catch (FileNotFoundException e) {

System.err.println("Fichier non trouvé");

}catch (IOException e) {

System.err.println("Impossible d’écrire dans le fichier");

}finally{

if (dos != null) {

try {dos.close(); // fermeture du flux }

catch (IOException e) {System.err.println("problème dans la fermeture du flux"); } }

}

} // voir class LectureEcritureBinaireFichier_New puis utiliser la fonction lectureBufferedTypee pour le teste

(43)

M.AFILAL 43

Sérialisation

Définition:

– La sérialisation consiste à pouvoir prendre un objet en mémoire et à en sauvegarder l'état sur un flux de données (vers un fichier, par exemple).

Pour qu'un objet puisse être sérialisé, il est nécessaire que sa classe implémente l'interface java.io.Serializable.

Cette interface ne contient aucune déclaration de méthode ;

– lorsqu'une classe implémente l'interface Serializable, elle « autorise » la sérialisation de ses instances.

Remarque

– Ce concept permettra de reconstruire, ultérieurement, l'objet en mémoire à l'identique de ce qu'il pouvait être initialement.

– La sérialisation peut donc être considérée comme une forme de persistance de données.

– Il est possible avec un même flux de sérialiser plusieurs objets les uns à la suite des autres. Ainsi plusieurs objets peuvent être sauvegardés. Dans ce cas, il faut

faire attention de relire les objets dans leur ordre d'écriture.

appeler plusieurs fois les méthodes de ObjectInputStream.

– La règle est la suivant : la désérialisation des objets doit être dans leur ordre d'écriture (de sérialisation)

le premier objet sérialisé est le premier objet désérialisé, le second écrit est le second lu, etc...

– Si la classe utilisée a changé entre le moment où elle a été sérialisée et le moment où elle est désérialisée, une exception est levée :

– java.io.InvalidClassException

(44)

M.AFILAL 44

Exemple

import java.io.Serializable;

public class PersonneSerialisee implements Serializable { – static private final long serialVersionUID = 6L;

– public String nom;

– public String prenom;

– public double age;

– public PersonneSerialisee(String nom, String prenom, double age) { this.nom = nom;

this.prenom = prenom;

this.age = age;

– }

– public String toString() {

return nom + " " + prenom + " " + age + " ans";

– } }

Remarque

– le serialVersionUID permet d'affecter un numéro de version à la classe.

Ce numéro doit normalement être changé, par exemple, lorsqu'un champs non- transient est ajouté ou supprimé de la classe.

– Théoriquement, c'est le développeur qui doit créer ce champs. Toutefois, si ce champs est absent, le compilateur générera un numéro automatique.

– Le champs serialVersionUID est utilisé lors de la désérialization afin de s'assurer que les versions des classes Java soient concordantes. Si ce n'est pas le cas, une

InvalidClassException sera levée.

(45)

M.AFILAL 45

Exemple

public void ecritureObjects(String nomFichier) {

– File fich = new File(nomFichier);

– ObjectOutputStream dos = null;

try {

– // création d'une personne

PersonneSerialisee p = new PersonneSerialisee("Dupont", "Albert", 88);

System.out.println("creation de : " + p);

dos = new ObjectOutputStream(new FileOutputStream(fich));

– // sérialisation : écriture de l'objet dans le flux de sortie dos.writeObject(p);

System.out.println(p + " a été sérialisé");

dos.flush(); //flush vide le buffer et force l'écriture dans le fichier binaire spécifié ;

}catch (FileNotFoundException e) {

System.err.println("Fichier non trouvé");

}catch (IOException e) {

System.err.println("Impossible d'ecrire");

e.printStackTrace();

} finally {

if (dos != null) {

try { dos.close(); // fermeture du flux }

catch (IOException e) { System.out.println("problème dans la fermeture du flux"); } }

}

} // voir class LectureEcritureBinaireFichier_New

(46)

M.AFILAL 46

Remarques

Remarque

– Il peut cependant être problématique que toutes les valeurs des variables soient sauvegardées car cela peut poser des problèmes de sécurité.

Java fournit pour cette raison le modificateur transient.

– Les variables déclarées avec le modificateur transient seront stockées (type et nom) mais pas leur valeur.

– Une fois désérialisées, elles auront les valeurs par défaut : 0 pour les nombres,

false pour un boolean,

null pour les objets. (ceci peut engendrer des problème avec un l’utilisation d’un objet nul)

– transient devant un attribut, entraine qu’il ne sera pas sauvegardé par writeObject() , ni lu par readObject( ), la valeur de l'attribut sera donc initialisée à null

Remarque

– Toutes les classes dérivées d’une class sérialisable sont aussi sérialisables.

– Lorsqu’une classe est désérialisée par Java, les champs de la super-classe qui ne serait pas sérialisable seront initialisés dans le constructeur vide sans argument.

(47)

M.AFILAL 47

Exemple pour la désérialisation

public void lectureObjects(String nomFichier) { – try {

ObjectInputStream dis = new ObjectInputStream(new FileInputStream(new File(nomFichier)));

PersonneSerialisee p = null;

– // désérialisation : lecture de l'objet depuis le flux d'entrée p = (PersonneSerialisee) dis.readObject();

if (p != null) {

– System.out.println(p + " a été désérialisé");

}

}catch (NullPointerException e) { System.out.println("Objet Fichier nul");

}catch (FileNotFoundException e) { System.out.println("Fichier non trouvé");

}catch (ClassNotFoundException e) { e.printStackTrace();

}catch (IOException e) {

System.out.println("Impossible de lire");

e.printStackTrace();

} finally {

if (dis != null) {

try { dis.close(); // fermeture du flux }

catch (IOException e) { System.out.println("problème dans la fermeture du flux"); } }

}

} // voir class LectureEcritureBinaireFichier_New

(48)

M.AFILAL 48

Sérialisation et l’héritage

Deux cas de figure pour le comportement de la sérialisation face à l'héritage.

– Premier cas de figure:

lorsqu'une classe hérite d'une classe sérialisable, elle se comporte comme si elle avait implémenté elle-même l'interface Serializable.

Les attributs de la classe mère sont sérialisés selon l'implémentation de celle-ci.

– Deuxième cas de figure:

une classe implémente l'interface Serializable et hérite d'une classe non sérialisable.

– Il y a ici deux points fondamentaux à savoir : les attributs hérités ne sont pas sérialisés.

il est nécessaire que la classe étendue (la classe mère) possède

un constructeur par défaut accessible ; dans le cas contraire, une

InvalidClassException est levée à l'exécution.

(49)

M.AFILAL 49

Sérialisation personnalisée

Il est possible de personnaliser la sérialisation d'un objet:

– dans ce cas, la classe doit implémenter l'interface Externalizable qui hérite de l'interface Serializable.

Cette interface définit deux méthodes publiques : readExternal() et writeExternal().

– Utiliser ces méthodes pour contrôler la façon d’enregistrer ou de lire des objets à stocker via un flux de données.

private void writeExternal (java.io.ObjectOutputStream out) throws IOException;

private void readExternal (java.io.ObjectInputStream in) throws IOException, ClassNotFoundException;

Par défaut

– la sérialisation d'un objet qui implémente cette interface ne prend en compte aucun attribut de l'objet (pas de sérialisation par défaut).

Remarque :

– le mot clé transient est donc inutile avec une classe qui implémente l'interface Externalisable

– Une classe implémentant l'interface Externalizeable doit posséder un constructeur par défaut public:

qui sera utilisé dans la déserialisation afin d’initialiser les champs sans valeur des objets stockés (surtout si cette classe hérite d’une classe non sérialisable)

Exemple

(50)

M.AFILAL 50

Sérialisation personnalisée

public class CryptageString implements Externalizable { static private final long serialVersionUID = 13L;

private int val; private String str;

public CryptageString( ) { str = ""; val = 0;}

public CryptageString(String str, int val) { this.str= str; this. val = val; }

/******************* Sérialisation des données. ******************************/

public void writeExternal(ObjectOutput out) throws IOException { // récupération du tableau de byte représentant str

byte[ ] tab = str.getBytes("UTF-8");

// cryptage de str = césar avec val

for(int i = 0; i < tab.length ; i ++) { tab[i] += val; };

out.writeLong(val * val); // écriture du carré de val out.writeObject(tab); // écriture du tableau de byte }

/******************** Désérialisation des données. ****************************/

public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { // lecture du carré de integer

val = (int) Math.sqrt(in.readLong());

// lecture du tableau de byte byte[ ] tab = (byte[ ]) in.readObject();

for(int i = 0; i < tab.length; i ++) { tab[i] -= val; } str = new String(tab, "UTF-8");

} }

(51)

M.AFILAL 51

Remarques importantes pour la sérialisation

Remarque pour l’exception StreamCorruptedException

– Si on appel une première fois la méthode ecritureObjet pour enregistrer un objet dans un fichier nomFichier, puis on ferme le flux utilisé.

Puis, si on enregistre encore un autre objet, en faisant appel à la méthode ecritureObjects en fermant le flux.

– Le fichier nomFichier sera modifier

– et si on veut le relire encore une fois on aura le déclanchement d’une

exception: Une exception de type StreamCorruptedException peut être levée – La même exception sera levée si le fichier a été corrompu par exemple en le

modifiant avec un éditeur.

– La sérialisation des objet devait se faire une seule fois avant la fermeture du flux utilisé pour cette tâche.

Remarque pour la désérialisation:

– la désérialisation de l'objet doit se faire avec la classe qui a été utilisée pour la sérialisation.

– Il est possible avec un même flux d'écrire plusieurs objets les uns à la suite des autres.

Ainsi plusieurs objets peuvent être sauvegardés.

Dans ce cas, il faut faire attention de relire les objets dans leur ordre d'écriture.

(52)

M.AFILAL 52

Remarques importantes pour la sérialisation

Remarque dans le cas de champ statique

Lors de la sérialisation, on aura seulement la valeur nulle qui sera affectée au champ statique.

– Pour remédier à cela, on utilisera, par exemple, le code suivant qui permet la sérialisation pour le champ statique : champStatique .

class newSerialisation implements Serializable { – private static final long serialVersionUID = 4L;

– private static int champStatique = 0;

// Autres champs: non-transient non-statique champs.

– /*Ceci impose que l’écriture et la lecture du champ statique doivent être traitées à part*/

– private void writeObject(ObjectOutputStream oos) throws IOException {

// appel des mécanismes de sérialisation automatique par défaut (via le mot sérialisable définissant la classe)

– oos.defaultWriteObject();

– oos.writeObject(new Integer(champStatique));

}

private void readObject(ObjectInputStream ois) throws ClassNotFoundException, IOException {

– ois.defaultReadObject();

– champStatique = (Integer) ois.readObject();

} }

(53)

M.AFILAL 53

Liste des différents flux primaires, classés par catégorie

bytes bytes

(54)

M.AFILAL 54

(55)

M.AFILAL 55

Accès séquentiel en mode texte

La question qu'on pourrait se poser est: Pourquoi des flux spéciaux pour les caractères alors que ce sont des données binaires ?

– La réponse est que Java, contrairement à beaucoup d'autres langages, utilise Unicode.

Ainsi, les caractères sont codés sur 16 bits et non sur 8.

Ces flux servent donc à gérer les jeux de caractères (conversion possible d'un jeu à l'autre: choix de codage approprié).

Les classes de flux gérant ce type d’accès offrent deux améliorations : un meilleur support de l’encodage des caractères lus.

des meilleurs performances.

– on peut fixer un autre encodage, pour la gestion des caractères, qui peut être différents de celui du système ,

Ce type d’accès est capable de lire ou écrire tout caractère Unicode.

Il faut privilégier ces classes pour être compatible avec les alphabets internationaux.

(56)

M.AFILAL 56

Accès séquentiel en mode texte

Les classes de flux gérant ce type d’accès sont les sous-classes des classes Reader et Writer.

– Attention:

Par défaut les objets, des classes Writer ou Reader, utilisent l’encodage privilégié par le système.

– Cela signifie que l’écriture dans un fichier, par exemple, peut aboutir à la perte des informations, due à un encodage incapable de prendre en compte certain caractère.

Les concepts et méthodes utilisés pour les flux binaires ont été adaptés aux flux de caractères. Il y a donc de fortes similitudes avec ce qui a été vu dans le cours de flux binaire.

Pour accéder à une source de données, il faut déterminer : L’accès en lecture ou en écriture

Le type de la source de données : fichier, mémoire, etc.….

La manière de gérer le flux : choisir le filtre adéquat (peut être aucun).

(57)

M.AFILAL 57

Accès séquentiel en mode caractère en lecture

La classe Reader fournit:

– Des méthodes permettant la lecture de caractères.

– Ses méthodes read( ) sont similaires à celle avec les flux de binaires.

– La seule méthode abstraite qu’elle implémente est la méthode : int read(char[ ] cbuff, int off, int len).

– Elle permet de lire un caractère ou un tableau de caractères

Elle stocke les len caractères lus dans le tableau de char à partir de la position off.

Autre méthodes de lecture – int read( ) :

Lit le prochain caractère sur le flux et le retourne sous forme d’int. Pour l’utiliser réellement sous forme de caractère (char), il sera nécessaire de faire une conversion explicite (cast).

– int read(char[] cbuff) :

Elle stocke les caractères lus dans le tableau de char.

Cette classe possède également les méthodes

– close( ), mark(int readlimit), markSupported( ), reset( ), skip(long n).

– Elle possède aussi une méthode boolean ready( ) qui teste s’il est possible de

lire sans bloquer le flux.

(58)

M.AFILAL 58

Accès séquentiel caractère en lecture

(59)

M.AFILAL 59

FilterReader :

classe abstraite permet de lire des flux de données filtrées, il faut utiliser ses sous classes.

PushBackReader:

permet de revenir en arrière dans un flux,

Elle est dotée d’une méthode unRead() qui permet de remettre du texte dans le flot d’entrée, comme s’il n’avait pas déjà été lu. « pas ou jamais utilisée »

PipedReader :

classes utilisée pour les communications via les réseaux et les gestions des processus.

InputStreamReader :

Cette classe va permettre la communication entre les flux d’entrée d’octets et les flux d’entrée de caractères.

En effet,

il va lire les octets pour ensuite les transformer en caractères en utilisant un jeu de caractères spécifique (Charset). «elle lit les octets et les décodes en caractères en utilisant un encodage »

Ce jeu de caractères sera celui de la plateforme par défaut, mais peut être spécifié par l’utilisateur lors de l’instanciation :

InputStreamReader(InputStream in, Charset cs).

Permet la conversion octets vers caractères.

Objectif :

choisir un encodage adapté aux type de données a lire.

construire un Reader à partir d’un InputStream. C’est particulièrement utile avec System.in.

FileReader:

cette classe (qui hérite de InputStreamReader) décrit tout flux texte entrant attaché à un fichier.

Accès séquentiel caractère en lecture

(60)

M.AFILAL 60

StringReader :

Cette classe permet la lecture d’une chaîne de caractères fournie dans le constructeur StringReader(String s).

CharArrayReader :

Cette classe permet la lecture d’un tableau de caractères « flux de caractères d’entrée ».

BufferedReader :

Cette classe va permettre

une lecture bufférisée des flux de caractères d’entrée,

la possibilité de fixer la taille du buffer dans le constructeur.

la possibilité de revenir en arrière dans la lecture, à l’aide des méthodes mark et reset void mark (int _limite) throws IOException

place une marque à la position courante de lecture. l’argument limite permet de fixer le nombre maximum de caractères qui pourront être lus en préservant la marque.

void reset ( ) throws IOException

remet la tête de lecture à la position de la dernière marque posée.

public long skip(long n) throws IOException Permet de sauter n caractères dans le flux

Un autre intérêt du BufferedReader est la disponibilité de la méthode readLine : String readLine ( ) throws IOException

renvoie la ligne suivante sous forme de String, ou null si on est à la fin du fichier.

ce sont des caractères Unicode qui sont lus, représentés par 2 octets consecutives.

LineNumberReader:

C’est une sous classe de BufferedReader, elle est dotée d’une méthode getLineNumber qui permet de connaître le numéro de la ligne courante.

Exemple: voir la classe LectureTextFichier

Accès séquentiel caractère en lecture

(61)

M.AFILAL 61

Exemple pour lecture de caractère

Remarque

– boolean markSupported( ): indique si le flux supporte la possibilité de marquer des positions

– boolean ready( ): indique si le flux est prêt à être lu Exemple

public static void testLectureTexte (InputStream input) throws IOException { – InputStreamReader f = new InputStreamReader(input);

– // Le résultat de read doit être un entier (à cause du -1 qui est renvoyé en fin de fichier)

– int cc;

– while ( (cc = f.read()) != -1){

– // Pour ranger cc dans un char, il faut un cast : char c= (char)cc;

– }

– f.close();

}

(62)

M.AFILAL 62

import java.io.*;

public class LectureTextFichier {

– void lectureSimple(String nomFile) { try {

/* lecture d'un fichier avec FileReader puis bufferisé avec affichage de ligne par la classe LineNumberReader */

– LineNumberReader in = new LineNumberReader (new FileReader(nomFile));

– String ligne;

/* lecture ligne par ligne*/

– while((ligne = in.readLine( )) != null) // fin de fichier si null System.out.println(in.getLineNumber( ) + " : " + ligne) ; – in.close( ) ;

}catch (IOException e) { – System.out.println(e);

– System.exit(0);

} – }

} // voir la classe LectureTextFichier

Accès séquentiel caractère en lecture

(63)

M.AFILAL 63

Accès séquentiel caractère en écriture

Pour l’écriture en mode texte:

– on utilise la classe Writer (classe abstraite) et ces classes dérivées.

elle permet l’écriture de flux de caractères.

elle impose l’implémentation des méthodes suivantes : – close( ):

Elle permet la fermeture d’un flux (il faudra tout d’abord vider les ressources utilisées par le flux avec la méthode flush( )).

– flush( ):

Elle permet de vider les ressources utilisées par le flux courant.

– write(char[] cbuf, int off, int len):

Elle permet l’écriture d’intervalle de tableau de caractères

Elle permet d’écrire un caractère ou un tableau de caractères

(64)

M.AFILAL 64

Accès séquentiel caractère en écriture

(65)

M.AFILAL 65

PipedWriter :

– classe utilisée pour les communications via les réseaux et les gestions des processus. Cette classe va être connectée à un PipedReader.

PrintWriter :

– Cette classe implémente toutes les méthodes de la classe PrintStream, elle produira une sortie formatée en string comme printf en C++.

– Les méthodes de la classe PrintWriter

ne déclenchant pas d’exception, ce sera à l’utilisateur de gérer cela en utilisant la méthode checkError( ), qui existe aussi dans PrintStream

– public boolean checkError ():

Appelle la méthode flush () et renvoie true si une erreur ou

exception est survenue pendant un appel aux autres méthodes de cette classe.

public static void main(String[] args) { – String s = "Hello World ";

– PrintWriter pw = new PrintWriter(System.out);

// on concatène le string – pw.append(s);

– // On vérifie s’il y’a une erreur ou problème de flush – System.out.println("" + pw.checkError( ) );

}

Accès séquentiel caractère en écriture

(66)

M.AFILAL 66

OutputStreamWriter :

– Cette classe va permettre

la communication entre les flux d’entrée de caractères et les flux d’entrée d’octets.

– Elle permet la conversion d’un flux de caractères en un flux de données binaires.

– En fait,

Ce flux convertie les caractères en bytes, avec un encodage utilisant un jeu de caractères spécifique (Charset = encodage utilisé), puis les écrits sous forme de flux de sortie en mode binaire.

L’encodage utilisé, en général, sera celui de la plateforme par défaut, L’encodage à utiliser (différent de celui du système utilisé), il peut être spécifié par l’utilisateur lors de l’instanciation, avec

– OutputStreamWriter (OutputStream out, Charset cs).

Accès séquentiel caractère en écriture

(67)

M.AFILAL 67

Exemple d’encodage

(68)

M.AFILAL 68

FilterWriter :

– Permettre d’écrire des flux de données filtrées.

BufferedWriter :

– Permet l’écriture Bufférisée de texte vers un flux de sortie de caractères FileWriter:

– écriture dans un fichier.

CharArrayWriter :

– Cette classe implémente une mémoire tampon de caractères qui peut être utilisée comme un objet Writer.

– On peut spécifier sa taille à l’aide du constructeur CharArrayWriter.

StringWriter :

– Cette classe représente un flux de caractères qui recueille sa sortie dans un objet StringBuffer,

lequel peut alors être utilisé pour construire une chaîne de caractères

Accès séquentiel caractère en écriture

(69)

M.AFILAL 69

Exemple _1

On utilise un objet adapté (ici un Writer pour l’écriture et un reader pour la lecture).

– public static void testEcritureTexte(String fname) throws IOException { – // On crée un objet Writer, ce qui ouvre le fichier fname

FileWriter f= new FileWriter(fname);// On utilise cet objet pour écrire f.write("Bonjours ");

f.write(" à tous.");

f.write(" Java c’est facile !");

f. flush( ); // on vide les ressources utilisées par le flux f f.close( ); // On ferme le flux

– }

– public static void testLectureTexte (String fname) throws IOException { FileReader f = new FileReader(fname);

int cc = f.read();

while (cc != -1){

// Pour ranger cc dans un char, il faut un cast : – System.out.println((char) cc);

cc = f.read(); // Lecture du suivant.

}

f.close();

– }

(70)

M.AFILAL

Exemple _2

Classe CompteReader fournie les fonctionnalités d’un Reader (Lecteur de caractères) et compte les caractères lus :

import java.io.*;

public class CompteReader extends Reader {

private Reader in; // ‘‘in’’ est le Reader dans lequel nous lirons private int total; // compteur de caractères

public CompteReader(Reader in) { this.in = in;

total = 0;

}

public int read(char[ ] s, int off, int len) throws IOException{

// On lit dans in, et on récupère le nombre de caractères lus dans nbr.

int nbr = in.read(s,off,len);

total += nbr;

return nbr;

}

public void close() throws IOException{

in.close();

}

public int getTotal() { return total;

} }

Remarque:

Quand on lit une donnée dans un CompteReader, avec read(), la méthode read de CompteReader utilise celle du Reader « in » pour lire effectivement les caractères.

(71)

M.AFILAL 71

import java.io.*;

public class Ecrire{

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

try{

– FileWriter fw=new FileWriter(“C:\\temp\\essai.txt");

– BufferedWriter bw= new BufferedWriter(fw);

– bw.write("Ceci est mon fichier");

– bw.newLine();

– bw.write("Il est à moi...");

– bw.close();

}catch (Exception e){

– System.out.println("Erreur "+ e);

} – } }

Exemple _3: écriture bufférisée dans un fichier ++

(72)

M.AFILAL 72

import java.io.*;

public class LireLigne{

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

try{

– FileReader fr = new FileReader(“C:\\temp\\essai.txt ");

– BufferedReader br = new BufferedReader(fr);

– while (br.ready()) System.out.println(br.readLine());

– br.close();

}catch (Exception e){

– System.out.println("Erreur "+e);

} – } }

Exemple _4: lecture bufférisée dans un fichier

Références

Documents relatifs

Les méthodes de clustering proposées représentent la première étape de notre mé- thode d'extraction de motifs séquentiels approximatifs dans les ux de données, mais ces

Nous avons vu dans ce chapitre que notre approche nous permet de générer des plans de requêtes efficaces autant pour la gestion de flux de données que pour la jointure avec un

Dans une réservation de style WF, le message RESV ne contient pas de FILTER_SPEC (après tous, c'est un filtre générique) et l'objet SENDER_TEMPLATE est ignoré (encore une

L’état dans lequel toutes les voies sont au rouge n’est pas nécessaire pour un carrefour à deux feux, mais devient nécessaire dans un problème à plus de deux feux, car la

Avec un serveur de données comme Oracle, Postgres, MySQL, MS-Access, respectant la norme SQL (Structured Query Language - langage normalisé de contrôle et interrogation des bases

- Une variable d’instance (pas static) final est constante pour chaque instance ; mais elle peut avoir 2 valeurs différentes pour 2 instances. - Une variable d'instance final

Fournit des méthodes pour écrire des données sous formes de types primitifs Java, dans un flux de sortie, de manière portable. – Donc, elle permet d'écrire tous les types de base

Dans cette optique, nous propo- sons l’utilisation d’un chiffrement homomorphe pour chiffrer les données stockées en mémoire et les maintenir sous forme chiffrée lors