59
1 COURS DE PROGRAMMATION ORIENTEE OBJET : Flux et Fichiers

COURS DE PROGRAMMATION ORIENTEE OBJET :

  • Upload
    mahon

  • View
    72

  • Download
    0

Embed Size (px)

DESCRIPTION

COURS DE PROGRAMMATION ORIENTEE OBJET :. Flux et Fichiers. FLUX ET FICHIERS. Flux et fichiers Les entrées et les sorties sont gérées par les objets de flux : Les données sont fournies au programme via un flux d’entrée . Les données ressortent via un flux de sortie. FLUX ET FICHIERS. - PowerPoint PPT Presentation

Citation preview

Page 1: COURS DE PROGRAMMATION  ORIENTEE OBJET :

1

COURS DE PROGRAMMATION ORIENTEE OBJET :

Flux et Fichiers

Page 2: COURS DE PROGRAMMATION  ORIENTEE OBJET :

2

FLUX ET FICHIERS

Flux et fichiers– Les entrées et les sorties sont gérées

par les objets de flux :• Les données sont fournies au

programme via un flux d’entrée.• Les données ressortent via un

flux de sortie.

Page 3: COURS DE PROGRAMMATION  ORIENTEE OBJET :

3

Les classes d’entrées/sorties– Elles sont définies dans le paquetage

java.io.

Entrée Sortie

Binaire InputStream OutputStream

Texte Reader Writer

FLUX ET FICHIERS

Page 4: COURS DE PROGRAMMATION  ORIENTEE OBJET :

4

Les classes d’entrées/sorties– InputStream et OutputStream

permettent de traiter les fichiers binaires.

– Les fichiers binaires sont des fichiers image, vidéo, audio et exécutables.

– Java les transfère en octets de 8 bits.

FLUX ET FICHIERS

Page 5: COURS DE PROGRAMMATION  ORIENTEE OBJET :

5

Les classes d’entrées/sorties– Reader et Writer permettent de

traiter les fichiers texte.– Les fichiers texte sont lus et écrits par

des éditeurs de texte.– Java les transfère sous forme de codes

Unicode de deux octets.

FLUX ET FICHIERS

Page 6: COURS DE PROGRAMMATION  ORIENTEE OBJET :

6

InputStream et ses sous-classes– La classe InputStream possède une seule

méthode abstraite : abstract int read() throws IOException qui lit un seul octet et renvoie cet octet ou bien -1 si la fin de la source de données a été atteinte.

– Chaque sous-classe concrète devra surcharger cette méthode.

Exemple : pour la sous-classe FileInputStream,la méthode read lit un seul octet dans un fichier.

FLUX ET FICHIERS

Page 7: COURS DE PROGRAMMATION  ORIENTEE OBJET :

7

InputStream et ses sous-classes– L’objet prédéfini System.in de type InputStream permet de saisir l’information à partir du clavier

– Après une opération de lecture dans un flux, il faut le fermer en appelant la méthode close qui libère les ressources.

FLUX ET FICHIERS

Page 8: COURS DE PROGRAMMATION  ORIENTEE OBJET :

8

InputStream et ses sous-classes– Exemples de sous-classes :

• AudioInputStream : lecture de données audio.

• DataInputStream : lecture des types primitifs de Java.

• FileInputStream : lecture dans un fichier sur disque.

• ZipInputStream : lecture de fichiers dans le format de compression ZIP.

FLUX ET FICHIERS

Page 9: COURS DE PROGRAMMATION  ORIENTEE OBJET :

9

InputStream et ses sous-classes– Combinaison de flux

• FileInputStream permet d’accéder aux données d’un fichier mais ne possède pas de méthode pour lire les types numériques.

• DataInputStream ne fournit pas de méthode pour accéder aux données d’un fichier mais possède des méthodes qui assemblent les octets en types de données numériques.

FLUX ET FICHIERS

Page 10: COURS DE PROGRAMMATION  ORIENTEE OBJET :

10

InputStream et ses sous-classes Combinaison de flux

Pour lire des nombres dans un fichier : On crée un objet FileInputStream en

appelant le constructeur :public FileInputStream(String name) throws FileNotFoundException

On passe cet objet au constructeur d’un objet DataInputStream

La classe DataInputStream fournit par exemple la méthode :public final double readDouble()throws IOException

FLUX ET FICHIERS

Page 11: COURS DE PROGRAMMATION  ORIENTEE OBJET :

11

InputStream et ses sous-classes Combinaison de flux

Pour lire des nombres dans un fichier :FileInputStream f =

new FileInputStream("test.txt");DataInputStream d =

new DataInputStream(f);

double s = d.readDouble();

FLUX ET FICHIERS

Page 12: COURS DE PROGRAMMATION  ORIENTEE OBJET :

12

OutputStream et ses sous-classes– La classe OuputStream possède une seule

méthode abstraite abstract void write(int b) qui écrit un octet vers une destination.

– Exemples de sous-classes: AudioOutputStream, DataOutputStream, FileOutputStream, ZipOutputStream.

– Deux autres méthodes:• void close() qui vide le tampon de sortie et

ferme le flux.• void flush() qui envoie vers la cible les données

se trouvant sur le tampon. Permet de forcer le vidage du tampon de sortie.

FLUX ET FICHIERS

Page 13: COURS DE PROGRAMMATION  ORIENTEE OBJET :

13

OutputStream et ses sous-classes– DataOutputStream

Fournit les méthodes pour écrire des données binaires de tous les types de base de Java :

– writeChars qui écrit un caractère Unicode sur 2 octets– writeInt qui écrit toujours un entier sur 4 octets– writeDouble qui écrit toujours un double sur 8 octets

Les sorties binaires produites par ces méthodes ne seront pas lisibles en utilisant les outils du système d’exploitation mais pourront être lues par un programme Java avec les méthodes correspondantes de la classe DataInputStream.

FLUX ET FICHIERS

Page 14: COURS DE PROGRAMMATION  ORIENTEE OBJET :

14

Avantages et inconvénients des fichiers binaires

– Avantages• compacts• efficaces• Indépendants des plates-formes

– Inconvénients• Les sorties binaires ne sont pas directement

lisibles par l’homme.

FLUX ET FICHIERS

Page 15: COURS DE PROGRAMMATION  ORIENTEE OBJET :

15

Les flux de texte– Codage de caractères :

• Java utilise le codage de caractères Unicode.

• Chaque système d’exploitation utilise son propre système de codage de caractères.

FLUX ET FICHIERS

Page 16: COURS DE PROGRAMMATION  ORIENTEE OBJET :

16

Les flux de texte– Codage de caractères :

Java va fournir des classes permettant – d’obtenir des caractères Unicode à partir d’un

flux d’entrée contenant des octets dans un codage particulier de type caractères (InputStreamReader).

– D’obtenir un flux d’octets dans un codage particulier de type caractères à partir d’un flux de caractères Unicode (OutputStreamReader).

FLUX ET FICHIERS

Page 17: COURS DE PROGRAMMATION  ORIENTEE OBJET :

17

Les classes Reader et Writer– Les méthodes de base des classes Reader et

Writer sont comparables à celles de InputStream et de OutputStream :abstract int read() throws IOException renvoie soit une unité de code Unicode (sous forme d’un entier entre 0 et 65535) soit -1 si la fin du fichier est atteinte.

abstract void write (int b)

FLUX ET FICHIERS

Page 18: COURS DE PROGRAMMATION  ORIENTEE OBJET :

18

Les classes Reader et Writer– Lecture de texte à partir d’un fichier :

FileReader• Permet de lire à partir d’un fichier des

caractères un par un.• Convertit les octets lus en caractères Unicode.• Constructeurs de la classe FileReader:

– public FileReader(String fileName) throws FileNotFoundException

– public FileReader(File file) throws FileNotFoundException

FLUX ET FICHIERS

Page 19: COURS DE PROGRAMMATION  ORIENTEE OBJET :

19

Les classes Reader et Writer– Lecture de texte à partir d’autres sources en entrée :

• Utiliser la classe InputStreamReader

• Exemple : Lecture à partir des frappes du clavier

InputStreamReader in = new InputStreamReader(System.in);

FLUX ET FICHIERS

Page 20: COURS DE PROGRAMMATION  ORIENTEE OBJET :

20

Les classes Reader et Writer

Ecriture de texte dans un fichier : FileWriter• Permet d’écrire dans un fichier des caractères un par

un.• Convertit les caractères Unicode en octets dans le

codage particulier de caractères du système d’exploitation.

• Constructeurs de la classe FileWriter:

public FileWriter(String fileName) throws FileNotFoundException

public FileWriter(File file) throws FileNotFoundException

FLUX ET FICHIERS

Page 21: COURS DE PROGRAMMATION  ORIENTEE OBJET :

21

Les classes Reader et Writer

Les sous-classes BufferedReader et PrintWriter :Par défaut, les flux ne sont pas bufférisés. Chaque caractère lu ou écrit sous forme de code Unicode entraîne un appel système. Si on souhaite lire les lignes les unes après les autres dans un fichier ou écrire des lignes dans un fichier, on pourra combiner les flux suivants :

Pour la lecture FileReader et BufferedReader .

Pour l’écriture FileWriter et PrintWriter.

FLUX ET FICHIERS

Page 22: COURS DE PROGRAMMATION  ORIENTEE OBJET :

22

La classe BufferedReader – Cette classe fournit la méthode readLine() :

public String readLine () throws IOException

• Exemple1 :FileReader f =

new FileReader ("texte.txt");BufferedReader b =

new BufferedReader ( f );String ligne = b.readLine ();

FLUX ET FICHIERS

Page 23: COURS DE PROGRAMMATION  ORIENTEE OBJET :

23

La classe BufferedReader • La méthode readLine renvoie null

lorsqu’il ne reste plus d’entrée.• Exemple2 :

BufferedReader b = new BufferedReader ( new InputStreamReader(System.in));

String s; while ((s= b.readLine())!=null){//traitement de s }

FLUX ET FICHIERS

Page 24: COURS DE PROGRAMMATION  ORIENTEE OBJET :

24

Les classes BufferedReader et Scanner

– La JDK5.0 propose la classe java.util.Scanner qui rend plus aisée la lecture et l’analyse des chaînes de caractères et des types primitifs en utilisant des expressions régulières.

FLUX ET FICHIERS

Page 25: COURS DE PROGRAMMATION  ORIENTEE OBJET :

25

Les classes BufferedReader et Scanner

FLUX ET FICHIERS

Page 26: COURS DE PROGRAMMATION  ORIENTEE OBJET :

26

Les classes BufferedReader et Scanner

Exemple :String input = "1 fish 2 fish red fish blue fish"; Scanner s = new Scanner(input).useDelimiter("\\s*fish\\s*"); System.out.print(s.nextInt()); System.out.print(s.nextInt()); System.out.print(s.next()); System.out.println(s.next()); s.close();

1 2 red blue

FLUX ET FICHIERS

Page 27: COURS DE PROGRAMMATION  ORIENTEE OBJET :

27

La classe PrintWriter– FileWriter et PrintWriter

• La classe PrintWriter fournit la méthode println() : public void println ( String x )

FileWriter fw = new FileWriter ("doc.txt");

PrintWriter out = new PrintWriter ( fw );out.println ( "ceci est un texte" );

FLUX ET FICHIERS

Page 28: COURS DE PROGRAMMATION  ORIENTEE OBJET :

28

Les classes d’entrées/sortiesExemple : Conversion d’un fichier texte en

majusculesimport java.io.*;public class ConvertMajuscules { public static void main (String [] args){ try{

FileReader f= new FileReader("in.txt"); BufferedReader in= new BufferedReader(f); PrintWriter out= new PrintWriter("out.txt"); String ligne = null; int nbLignes =0;

FLUX ET FICHIERS

Page 29: COURS DE PROGRAMMATION  ORIENTEE OBJET :

29

try{//utilisation de la ressourcewhile ((ligne=in.readLine())!=null){ out.println(ligne.toUpperCase()); ++nbLignes;}System.out.println( "Copies de "+

nbLignes + "lignes.");}finally {//libération de la ressource in.close(); out.close();}} catch (IOException e){ System.out.println("exception "+e);}}  //fin du main}//fin de ConvertMajuscules

FLUX ET FICHIERS

Page 30: COURS DE PROGRAMMATION  ORIENTEE OBJET :

30

Les classes d’entrées/sorties– Exemple2 : Lire un fichier texte et en

compter le nombre de caractères.import java.io.*;public class CompteCaracteres{ File f; public int nbCaracteres(String nom){

    int nb = 0;    f = new File(nom);    FileReader fr= new FileReader(f);    while(fr.read()!= -1)     nb++;    return nb;}

}

FLUX ET FICHIERS

Page 31: COURS DE PROGRAMMATION  ORIENTEE OBJET :

31

Les classes d’entrées/sorties– Exemple2 : Lire un fichier texte et en

compter le nombre de caractères. Le nom du fichier est passé en paramètre sur la ligne de commande.

public class Main{ public static void main(String[] args){

 CompteCaracteres wc = new CompteCaracteres();

 System.out.println(wc.nbCaracteres(args[0]));

}}

FLUX ET FICHIERS

Page 32: COURS DE PROGRAMMATION  ORIENTEE OBJET :

32

Les classes d’entrées/sorties– Exemple2 : Lire un fichier texte et en

compter le nombre de caractères.On obtient deux erreurs de compilation:ligne 12: unreported exception java.io.FileNotFoundException; must be caught or declared to be thrownFileReader fr = new FileReader(f);

ligne 13: unreported exception java.io.IOException; must be caught or declared to be thrownwhile(fr.read() != -1)

FLUX ET FICHIERS

Page 33: COURS DE PROGRAMMATION  ORIENTEE OBJET :

33

Les classes d’entrées/sorties– Exemple2 : Lire un fichier texte et en

compter le nombre de caractères.

Modifier le code pour capturer les exceptions, et notamment celle provoquée par le fichier non trouvé, faites en sorte que l’utilisateur puisse saisir un autre nom.

FLUX ET FICHIERS

Page 34: COURS DE PROGRAMMATION  ORIENTEE OBJET :

34

– Exemple2 : Lire un fichier texte et en compter le nombre de caractères.

import java.io.*;public class CompteCaracteres{

File f;public int nbCaracteres(String nom)throws IOException, FileNotFoundException {  int nb = 0;  f = new File(nom);  FileReader fr= new FileReader(f);  while(fr.read() != -1)   nb++;    return nb;  }}

FLUX ET FICHIERS

Page 35: COURS DE PROGRAMMATION  ORIENTEE OBJET :

35

import java.io.*;public class Main { public static void main(String[] args) throws

IOException {boolean fichierInexistant = true;String monFichier = args[0];boolean problemeFichier = false;CompteCaracteres wc= new CompteCaracteres();while (fichierInexistant == true) {

if (problemeFichier == true){ System.out.print("Autre nom : ");    // conversion octet / caractères Unicode    Scanner sc = new Scanner (System.in);

monFichier = sc.nextLine();}

…      

FLUX ET FICHIERS

Page 36: COURS DE PROGRAMMATION  ORIENTEE OBJET :

36

try {int nb =

wc.nbCaracteres(monFichier); System.out.println(nb);

  fichierInexistant = false;} catch(FileNotFoundException e){

System.out.println(" non trouve" ); problemeFichier =true;}

   } }}

FLUX ET FICHIERS

Page 37: COURS DE PROGRAMMATION  ORIENTEE OBJET :

37

Exemples d’utilisation des flux– Exemple1: Sauvegarder des données du

même type CompteCourant au format texte.

– Exemple2 : Sauvegarder des données polymorphes, par exemple le contenu d’un tableau de comptes bancaires de type CompteCourant ou CompteEpargne.

FLUX ET FICHIERS

Page 38: COURS DE PROGRAMMATION  ORIENTEE OBJET :

38

Exemples d’utilisation des flux– Exemple1: On complète la classe CompteCourant

avec deux méthodes:public void ecrire(PrintWriter sortie){sortie.println( getNom() +"|" + getAdresse()

+"|" + getSolde()+"|"+tauxAgios );}qui utilise un flux de sortie bufférisé pour écrire les

données correspondant à un compte courant , les champs étant séparés par le délimiteur (|).

Exemple : Dupont|rue de Bourgogne|1000|0.2

FLUX ET FICHIERS

Page 39: COURS DE PROGRAMMATION  ORIENTEE OBJET :

39

public void lire (BufferedReader entree) throws IOException{

String s =entree.readLine();StringTokenizer str= new StringTokenizer(s,"|");

this.setNom(str.nextToken());this.setAdresse(str.nextToken());this.crediter(Integer.parseInt(str.nextToken()));this.tauxAgios=Double.parseDouble(str.nextToken();

FLUX ET FICHIERS

Page 40: COURS DE PROGRAMMATION  ORIENTEE OBJET :

40

public void lire (BufferedReader entree) throws IOException{

String l =entree.readLine(); Scanner s= new Scanner(l).useDelimiter("|"); System.out.println(s.nextInt()); System.out.println(s.nextInt()); System.out.println(s.next());

setNom(s.next());setAdresse(s.next());crediter(s.nextInt()));setTauxAgios(s.nextDouble());

}

FLUX ET FICHIERS

Page 41: COURS DE PROGRAMMATION  ORIENTEE OBJET :

41

Exemples d’utilisation des fluxExemple1:

La méthode lire utilise un flux d’entrée bufférisé pour lire les données correspondant à un compte courant.1 - Lecture de la ligne avec la méthode readLine().2 – Extraction de chaque champ. Utilisation de la classe java.util.StringTokenizer en lui passant le délimiteur choisi en paramètre (ici : |).

FLUX ET FICHIERS

Page 42: COURS DE PROGRAMMATION  ORIENTEE OBJET :

42

Exemples d’utilisation des fluxExemple1: Application 1. Ecriture du contenu d’un tableau de comptes

courants dans un fichier.2. Lecture des enregistrements de plusieurs

comptes courants à partir d’un fichier et création du tableau de comptes courants correspondant.

FLUX ET FICHIERS

Page 43: COURS DE PROGRAMMATION  ORIENTEE OBJET :

43

Exemples d’utilisation des fluxExemple1: Application public static void ecrire(CompteCourant[]

lesComptes, PrintWriter sortie) {

sortie.println(lesComptes.length); for (CompteCourantcompte:lesComptes) { compte.ecrire (sortie); }}

FLUX ET FICHIERS

Page 44: COURS DE PROGRAMMATION  ORIENTEE OBJET :

44

Exemples d’utilisation des fluxExemple1: Application public static CompteCourant[]

lireDonnees(BufferedReader entree) throws IOException {

int n= Integer.parseInt(entree.readLine()); CompteCourant[] lesComptes=

new CompteCourant[n]; for (int i = 0; i<lesComptes.length; i++){ lesComptes[i] = new CompteCourant(); lesComptes[i].lireDonnees(entree); } return lesComptes;}

FLUX ET FICHIERS

Page 45: COURS DE PROGRAMMATION  ORIENTEE OBJET :

45

Exemples d’utilisation des flux– Exemple2 :

• Pour enregistrer dans un fichier agence.txt des comptes courants et des comptes d’épargne, il faudrait :

– enregistrer le type de chaque objet.– Enregistrer les données de l’objet

• Pour lire le fichier, il faudrait– Lire le type de l’objet– Créer un objet vide de ce type– Y placer les données provenant du fichier

FLUX ET FICHIERS

Page 46: COURS DE PROGRAMMATION  ORIENTEE OBJET :

46

Les flux d’objets et la sérialisationUne solution adaptée aux enregistrements de différents types :

• Ecriture d’un objet avec la classe ObjectOutputStream

• Lecture d’un objet avec la classe ObjectInputStream

FLUX ET FICHIERS

Page 47: COURS DE PROGRAMMATION  ORIENTEE OBJET :

47

Les flux d’objets et la sérialisation– Ecriture d’un objet avec la méthode

writeObject de la classe ObjectOutputStream

ObjectOutputStream sortie = new ObjectOutputStream (new FileOutputStream("agence.ser"));

CompteBancaire c1 = new CompteCourant ("Dupont", "a1",0.2);sortie.writeObject(c1);

FLUX ET FICHIERS

Page 48: COURS DE PROGRAMMATION  ORIENTEE OBJET :

48

Les flux d’objets et la sérialisation– Lecture d’un objet avec la méthode

readObject de la classe ObjectInputStream

ObjectInputStream entree = new ObjectInputStream (new FileInputStream("agence.txt"));

CompteBancaire c1= (CompteBancaire)entree.readObject();

FLUX ET FICHIERS

Page 49: COURS DE PROGRAMMATION  ORIENTEE OBJET :

49

Les flux d’objets et la sérialisation– La classe CompteBancaire doit

implémenter l’interface Serializable.

– Cette interface ne possède aucune méthode.

FLUX ET FICHIERS

Page 50: COURS DE PROGRAMMATION  ORIENTEE OBJET :

50

Exemples d’utilisation des flux– Retour à l’exemple2 : Ecriture dans le fichier

agence.txt du contenu d’un tableau de comptes bancaires

CompteBancaire[] lesComptes = new CompteBancaire[2];

CompteBancaire c1 = new CompteCourant ("Duval", "a2",0.02);

c1.crediter (500);CompteBancaire c2 = new CompteEpargne

("Martin", "a3",0.03);c2.crediter(200);

FLUX ET FICHIERS

Page 51: COURS DE PROGRAMMATION  ORIENTEE OBJET :

51

Exemples d’utilisation des flux– Retour à l’exemple2 : Ecriture dans le fichier

agence.txt du contenu d’un tableau de comptes bancaires

lesComptes[0] = c1;lesComptes[1] = c2;ObjectOutputStream sortie = new

ObjectOutputStream (new FileOutputStream("agence.txt"));

sortie.writeObject(lesComptes);

FLUX ET FICHIERS

Page 52: COURS DE PROGRAMMATION  ORIENTEE OBJET :

52

Exemples d’utilisation des flux– Exemple2 : Lecture dans le fichier agence.txt pour

créer un tableau de comptesObjectInputStream entree = new ObjectInputStream (new

FileInputStream("agence.txt"));CompteBancaire[] lesNouveauxComptes =

(CompteBancaire[])entree.readObject();lesNouveauxComptes [0].traitementQuotidien();lesNouveauxComptes [1].traitementQuotidien();

Les objets sont recréés avec leur type correct, CompteCourant ou CompteEpargne.

FLUX ET FICHIERS

Page 53: COURS DE PROGRAMMATION  ORIENTEE OBJET :

53

La sérialisation– Que se passe-t-il quand plusieurs objets

contiennent une référence à un même objet?

:ClasseA

:ClasseA

:ClasseB

x

x

:ClasseA désigne un objet instance de la ClasseA

FLUX ET FICHIERS

Page 54: COURS DE PROGRAMMATION  ORIENTEE OBJET :

54

La sérialisation– Il ne faut pas que l’objet de type ClasseB

soit enregistré deux fois dans le fichier sinon au rechargement du fichier, on aura une nouvelle configuration:

:ClasseA

:ClasseA

:ClasseBx

x:ClasseB

FLUX ET FICHIERS

Page 55: COURS DE PROGRAMMATION  ORIENTEE OBJET :

55

La sérialisation– Il faut que les références aux objets soient

copiées et rechargées telles qu’elles sont initialement.

– Java utilise la sérialisation des objets pour garantir cela :

• Tous les objets sauvegardés sur disque reçoivent un numéro d’ordre (1, 2, 3…)

• Quand un objet est enregistré sur disque, il faut rechercher si le même objet a déjà été sauvegardé.

• Si c’est le cas, l’objet est marqué comme « identique à un objet déjà sauvegardé et possédant le numéro d’ordre x ».

FLUX ET FICHIERS

Page 56: COURS DE PROGRAMMATION  ORIENTEE OBJET :

56

La sérialisation

:ClasseA

:ClasseA

:ClasseB

x

x

MEMOIRE

1 2 3:ClasseA :ClasseA :ClasseB

x = x = 3 3

FICHIER

FLUX ET FICHIERS

Page 57: COURS DE PROGRAMMATION  ORIENTEE OBJET :

57

Extensions

« Conclusion »

Flux = café !

Page 58: COURS DE PROGRAMMATION  ORIENTEE OBJET :

5858

Patron décorateur / decorator Les E/S en Java : écrire son propre décorateur de Streampublic class MinusculeInputStream extends FilterInputStream {

public MinusculeInputStream(InputStream in) {

super(in);

}

public int read() throws IOException {

int c = super.read();

return (c == -1 ? c : Character.toLowerCase((char)c));

}

public int read(byte[] b, int offset, int len) throws IOException {

int result = super.read(b, offset, len);

for (int i = offset; i < offset+result; i++) {

b[i] = (byte)Character.toLowerCase((char)b[i]);

}

return result;

}

}

Page 59: COURS DE PROGRAMMATION  ORIENTEE OBJET :

5959

décorateur de Stream Les E/S en Java : écrire son proprepublic class TestEntree {

public static void main(String[] args) throws IOException {

int c;

try {

InputStream in =

new MinusculeInputStream(

new BufferedInputStream(

new FileInputStream("test.txt")));

while((c = in.read()) >= 0) {

System.out.print((char)c);

}

in.close();

} catch (IOException e) {

e.printStackTrace();

}

}

}