C. Recanati
InHM Java
Master M1

TP n° 4 : exercices supplémentaires

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.
  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.

  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é.
  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é.

Eléments de correction pour l’exercice 3
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
		}