C.
RECANATI
IHM
Java
Master M1
2005
TP n¡ 4-5
Exercice
1: Sorties mises en tampon (=
« bufferisées ») vers un
fichier.
1) Ecrire un programme qui
calcule les 200 premiers nombres premiers et les stocke dans un tableau,
considéré ici comme tampon (ou, pour utiliser le terme anglais,
considéré ici comme buffer).
2) Ecrire ensuite les nombres
trouvés dans le fichier intitulé
« premiers.bin » d’un répertoire
« DonnesUtilisables », en faisant les tests
nécessaires pour vérifier que
« DonnesUtilisables » correspond bien à un nom de
répertoire (et créer ce répertoire s’il
n’existe pas).
3) Créer un flot de
sortie des données du tableau tampon vers le fichier
« premiers.bin », et écrire les nombres premiers
(du tableau) dans ce fichier à l’aide de la
méthode writeLong(). Fermer
ensuite le flot et en imprimer la taille. Le résultat obtenu vous
semble-t-il raisonnable ? (rappel : vous devez avoir écrit 200
valeurs de type long de 8 octets chacune).
Exercice
2 : (variante,
si vous en avez le temps ou l’envie …)
A partir de l’exercice
précédent, écrire un fichier compressé (format ZIP)
dans le même répertoire, contenant les mêmes sorties
(nombres premiers) compressées.
F on
crée un flot de sortie Zip (ZipOutputStream au lieu de créer un dataOutputStream) ;
on crée une entrée zip pour le fichier (objet de
type ZipEntry) et on écrit dans le flot de sortie zip avec
la méthode putNextEntry().
On a donc le bout de code
suivant :
ZipEntry monEntreeZip = new
ZipEntry(nomFichier) ;
monFichierZip.putNextEntry(monEntreeZip) ;
Créer ensuite le flot
de sortie vers le flot de sortie zip et écrire le tableau
d’entiers dedans.
Eléments de
correction
Exercice
1:
import java.io.* ;
import java.util.zip.* ;
public class TestDeSortieDeNombresPremiers {
public static void main (String [ ] args ) {
long [ ] premiers = new long[200] ;
premiers[0] = 2 ;
premiers[1] = 3 ;
int compteur = 2 ; // nb premiers trouvés jusqu’à présent
long nombre = 5 ; // l’entier suivant à tester
exterieur : for ( ; compteur < premiers.length ; nombre += 2L) {
// le div. max à tester est la racine carrée du nombre
long limite = (long)Math.ceil
(Math.sqrt((double) nombre)) ;
for (int i=1 ; i<count && premiers[i] <= limite ; i++)
if (nombre%premiers[i] == 0) // diviseur ?
continue exterieur ; // oui, essayer suivant
premiers [compteur++] = nombre ; // en voilà un !
}
// écrire les nombres premiers dans un fichier
try {
String nomDuRepertoire = « ../DonneesUtilisables » ;
String nomFichier = « premiers.bin » ; // nom du fichier
File monRepNbPremiers = new File (nomDuRepertoire) ;
if ( !monRepNbPremiers.exists()) // s’il le rep n’existe pas
monRepNbPremiers.mkdir() ; // le créer
else
if ( !monRepNbPremiers.isDirectory()) {
System.out.println(nomDuRepertoire +
« n’est pas un répertoire ») ;
return ;
}
// créer l’objet File
File fichierNbPremiers = new File (monRepNbPremiers,
nomFichier) ;
fichierNbPremiers.createNewFile() ; // s’il n’existe pas, le créer
// créer un flot de sortie des données mis en tampon pour
// le fichier
DataOutputStream premiersStream
= new DataOutputStream (
new BufferedOutputStream (
new FileOutputStream
(fichierNbPremiers))) ;
// écrire les nb premiers dans le fichier
for (int i=0 ; i<premiers.length ; i++)
premiersStream.writeLong(premiers[i]) ;
premiersStream.close() ;// vider et fermer le fichier
System.out.println(« Taille du fichier = »
+ premiersStream.size()) ;
}
catch (IOException e)
System.out.println(« IOException » + e
+ « est survenue ») ;
}
}
Exercice
2:
import java.io.* ;
import java.util.zip.* ;
public class TestDeSortieDeNombresPremiersZip {
public static void main (String [ ] args ) {
long [ ] premiers = new long[200] ;
premiers[0] = 2 ;
premiers[1] = 3 ;
int compteur = 2 ; // nb premiers trouvés jusqu’à présent
long nombre = 5 ; // l’entier suivant à tester
exterieur : for ( ; compteur < premiers.length ; nombre += 2L) {
long limite = (long)Math.ceil
(Math.sqrt((double) nombre)) ;
for (int i=1 ; i<count && premiers[i] <= limite ; i++)
if (nombre%premiers[i] == 0) // diviseur ?
continue exterieur ; // oui, essayer suivant
premiers [compteur++] = nombre ; // en voilà un !
}
try {
String nomDuRepertoire = « ../DonneesInutilisables » ;
String nomDuZip = « premiers.zip » ; // l’archive
String nomFichier = « premiers.bin » ; // fichier compressé
File monRepNbPremiers = new File (nomDuRepertoire) ;
if ( !monRepNbPremiers.exists())
monRepNbPremiers.mkdir() ;
else
if ( !monRepNbPremiers.isDirectory()) {
System.out.println(nomDuRepertoire
+ « n’est pas un répertoire ») ;
return ;
}
// créer l’objet File
File monZipNbPremiers = new File (monRepNbPremiers,
nomDuZip) ;
monZipNbPremiers.createNewFile() ; // s’il n’existe pas, le créer
// créer le flot de sortie zip
ZipOutputStream monFichierZip
= new ZipOutputStream (
new FileOutputStream (
monZipNbPremiers))) ;
// créer l’entrée zip pour le fichier et l’écrire dans le flot
// de sortie zip
ZipEntry monEntreeZip = new ZipEntry (nomFichier) ;
monFichierZip.putNextEntry(monEntreeZip) ;
// créer le flot de sortie vers le flot de sortie zip
DataOutputStream monFichier
= new DataOutputStream (
new BufferedOutputStream
(monFichierZip)) ;
// écrire les nb premiers dans le fichier
for (int i=0 ; i<premiers.length ; i++)
monFichier.writeLong(premiers[i]) ;
monFichier.flush() ; // s’assurer que tout est écrit
monFichierZip.closeEntry() ; //terminer l’entrée zip
monFichier.close() ; // fermer le flot de fichier
System.out.println(« Taille du fichier = » +
monFichier.size()) ;
System.out.println(« Taille du fichier compressé = »
+ monEntreeZip.getCompressedSize()) ;
}
catch (IOException e)
System.out.println(« IOException » + e
+ « est survenue ») ;
}
}
Rappels
sur flots d’entrée et flots
d’objets :
Ø
Les opérations de flots d’entrée
d’octets sont définies par des sous-classes de la classe abstraite
InputStream, et celles sur les flots d’entrée de caractères
par les sous-classes de Reader
Ø
Les classes de flots d’entrée
filtrés complètent les classes de flots de sortie
filtrés
Ø
La classe System de java.lang définit les
membres in, out et err (de type PrintStream) pour représenter
respectivement le flot d’entrée standard et les flots de sortie
standard et d’erreur standard
Ø
La classe RandomAccessFile permet de lire et d’écrire dans un
fichier
Ø
On peut utiliser la classe StreamTokenizer pour lire
des données formatées à partir d’un flot
En
outre :
Ø
La sérialisation d’objets est prise en
charge via les classes
ObjectOutputStream et
ObjectInputStream
Ø
Les objets sont écrits dans un fichier en
appelant la méthode writeObject() de l’objet ObjectOutputStream
correspondant au fichier
Ø
Les objets sont lus
dans un fichier en appelant la méthode readObject() de l’objet
ObjectInputStream correspondant au fichier
Exercice
3 : lecture
à partir du fichier premiers.bin
1) Créez un programme
permettant de lire un fichier de nombres premiers tel qu’il aurait
été créé dans l’exercice
1.
2) Affichez à
l’écran ces données à l’aide d’un flot
de caractères.
F Pour la
question 1) le principe est analogue à ce qui a été fait
pour écrire les données binaires dans un flot de sortie : il
faut créer un objet DataInputStream à partir
d’un FileInputStream.
Pour la question 2) utiliser
un objet FormatWriter qui gère l’affichage à
l’écran.
Exercice
4: (variante) lecture à partir du
fichier compressé.
F on
créera un ZipInputStream (intitulé monFichierZip) à partir du FileInputStream
et un ZipEntry à partir de monFichierZip en faisant appel à getNextEntry().
Ensuite on
crée un DataInputStream bufferizé à partir de monFichierZip . Le reste est inchangé.
question 1) :
import java.io.* ;
public class LirePremiers {
public static void main (String [ ] args ) {
try {
String nomDuRepertoire = « ../DonneesInutilisables » ;
String nomFichier = « premiers.bin » ;
File mesNbPremiers = new File (nomDuRepertoire,
nomFichier) ;
DataInputStream premiersInt
= new DataInputStream (
new FileInputStream (
mesNbPremiers))) ;
// Ici, le code permettant de lire les nombres
// les nombres premiers dans le flot précédant
// et de les afficher à l’écran (question 2)
out.close() ;
premiersInt.close() ;
}
catch (FileNotFoundException e) {
System.err.println(e);
return ;
}
catch (IOException e) { // Exception de lecture de fichier
System.err.println(« Erreur lecture fichier d’entrée »
+ e);
return ;
}
}
}
question 2) :
// Créer un flot de sortie de caractères formaté par défaut
FormatWriter out = new FormatWriter (
new BufferedWriter (
new FileWriter (FileDescriptor.out))) ;
long [ ] Premiers = new long [6] ; // tableau d’une ligne boolean EOF = false ; // indicateur de fin de fichier
while ( !EOF) {
int index = 0 ;// index pour stocker les nombres premiers
try {
// remplir la ligne avec les nbs venant du fichier
for (index = 0 ; index < Premiers.length ; index++)
Premiers [index] = premiersInt.readLong() ;
}
catch (EOFException e) {
EOF = true ; // mettra fin à la boucle
}
// Afficher les nombres premiers qui sont
// dans le tableau Premiers sur une ligne de sortie
for (int j = 0 ; j < index ; j++)
out.print(Premiers[j]) ;
out.println() ; // passer à la ligne suivante
}