Fichier et Stream d’Entrée-Sortie IFT1025, Programmation 2 Jian-Yun Nie.

Slides:



Advertisements
Présentations similaires
Module Systèmes d’exploitation
Advertisements

Quelques classes. La classe Object Il s agit de la classe principale, elle contient les fonctions : protected Object clone() qui crée et retourne une.
Stockage de données.
Sérialisation des objets
Le mécanisme des exceptions
Flots et Sérialisation des objets
Programmation Réseaux Illustration : Les Sockets en Java Anne-Marie Déry À travailler seuls Concepts généraux Mise en œuvre Java.
La classe String Attention ce n’est pas un type de base. Il s'agit d'une classe défini dans l’API Java (Dans le package java.lang) String s="aaa"; // s.
Vocabulaire pour la passage du modèle conceptuel des données au modèle relationnel des données. MCDMRD EntitéTable PropriétésChamps, attribut IdentifiantClé
Approfondissement du langage
(Classes prédéfinies – API Java)
Voisin-Polian : Introduction à Java 1 Introduction à Java - les flots - Frédéric VOISIN – Nicole POLIAN FIIFO - « Remise à Niveau »
Plan du cours La sérialisation: – comment stocker et restaurer les Objets? Les interfaces graphiques et la programmation évènementielle. –Comment concevoir.
Gestion de FICHIERS.
JAV - TD 6 Structures de données JAVA
FLSI602 Génie Informatique et Réseaux
1 Le mécanisme des exceptions Qu'est-ce qu'une exception? Comment définir et signaler des exceptions? Comment récupérer des exceptions?
Structures collectives en Java
Introduction à la programmation (420-PK2-SL) cours 12 Gestion des applications Technologie de linformation (LEA.BW)
COURS DE PROGRAMMATION ORIENTEE OBJET :
Les méthodes en java Une méthode est un regroupement d’instructions ayant pour but de faire un traitement bien précis. Une méthode pour être utilisée.
Mémoire périphérique Stockage primaire: Mémoire principale (RAM)
Cours d ’Informatique, DEUG 2 MASS/MIASS
1 Cours JAVA / Y.Laborde Java : Les FLUX de données Les flux de données introduction les flux binaires les flux binaires de sortie (FBS) les flux binaires.
IFT1025, Programmation 2 Jian-Yun Nie
Introduction au paradigme objet Concepts importants surcharge (overload) redéfinition (override) Définition d’une classe Définition des attributs.
Système d’Exploitation
Master 1 SIGLIS Java Lecteur Stéphane Tallard Chapitre 5 – Héritage, Interfaces et Listes génériques.
Les fichiers binaires en C++
FICHIERS : Définition : Algorithme général:
Programmation Orienté Objet applications au langage Java
Présentation Structures de Données et TDA
Gestion de Fichiers Tri Interne Efficace et Tri Externe.
IFT 6800 Atelier en Technologies d’information
1 IFT 6800 Atelier en Technologies dinformation Le langage de programmation Java chapitre 3 : Classes et Objects.
COURS DE PROGRAMMATION ORIENTEE OBJET :
COURS DE PROGRAMMATION ORIENTEE OBJET :
99 Réutilisation du code grâce à l'héritage. 9-2 Objectifs À la fin de ce cours, vous serez capables de : Définir l'héritage Utiliser l'héritage pour.
1111 Gestion des exceptions Objectifs À la fin de ce cours, vous serez capables de : • Expliquer les concepts de base de la gestion des exceptions.
1212 Entrée et sortie de fichiers Objectifs À la fin de ce cours, vous serez capables de : • Lire à partir de la console • Écrire sur la console.
J201 (JOC) Java Avancé juin 2007 ~ Brigitte Groléas ~
1 Fichers Binaires, Accès Direct et Objets. 2 Données binaires. Il s'agit ici de lire et écrire des données binaires par opposition à du texte. Pour ce.
Mastère MIAGE, Compléments de RMI. Mastère MIAGE, Passage de paramètres Le but de RMI est de masquer la distribution Idéalement, Il faudrait.
Cours 7 Classes locales Clonage Divers: tableaux.
Cours Les flux ou streams. Cours 162 Flux : objet possédant des méthodes capables de lire ou écrire des flots d’octets sur tout support (mémoire,
CEG3585/CEG3555 Tutorat 2 Hi ver 2013.
Master 1 SIGLIS Java Lecteur Stéphane Tallard Les erreurs communes en Java.
Tutorat en bio-informatique
12/04/ Les exceptions Cours 11 Cours 11.
Entrées / Sorties.
Strings et Tableaux en Java
Les sockets.
Les classes et les objets Les données finales class A { … private final int n = 20 ; // la valeur de n est définie dans sa déclaration … } class A { public.
Schéma de conception Factory Method Exemple Sylvain Giroux.
C# de plus près.  Ce sont globalement les mêmes que Java : ◦ Int(int16, int32), float, double, bool,…  Les classe « communes » sont également les mêmes.
Héritage H. Batatia. plan Notion (que signifie l’héritage) Ecriture en java Héritage multiple (interdit) Instanciation (partie propre et partie héritée)
Les fichiers 1ère partie
Les variables fichiers. Le type fichier On manipule les fichiers par l’intermédiaire de structures FILE décrites dans stdio.h FILE *monFichier; –Nom physique.
Cours 4 (14 octobre) Héritage. Chapitre III Héritage.
1 Chapitre III (~70 transparents) Compléments. 2 Au sommaire de ce chapitre 1. Les fichiers Les classes utilitaires
Ingénierie des réseaux - Chapitre 2 bis Les sockets en Java
Fichier et Stream d’Entrée-Sortie IFT1025, Programmation 2 Jian-Yun Nie Version court par Douglas Eck; Version
Introduction à la programmation objet avec java
JAVA Les Entrées-sorties
pour les programmeurs en C++ Java 2 Part 1 3 Histoire de Java Projet de connexion des machines: 1991 Le nom Java a été introduit dans un café Développé.
Fichiers et entrées-sorties en Java File and Input-ouput in Java J.M. Vanel Conseil informatique, architecture
Master Réseaux et Systèmes Distribués (RSD) Algorithmique des systèmes
Schéma de conception Factory Method Exemple
STREAMS (et fichiers).
Lecture/Écriture de fichiers (I/O)
Transcription de la présentation:

Fichier et Stream d’Entrée-Sortie IFT1025, Programmation 2 Jian-Yun Nie

Concepts Notion de fichier et de stream Opérations: ouverture, lecture/écriture, fermeture Format texte vs. binaire Accès séquentiel vs. aléatoire Organisation des indexes

Fichier Unité de stockage des données, sur disque dur, stockage permanent (vs. en mémoire vive) Un fichier contient un ensemble d’enregistrements Traitement fichier CPU Mémoire vive tampon

Fichier en Java Stream: une suite de données (octets ou caractères)

Opérations typiques Lecture: –Ouvrir un stream –Lire tant qu’il y a des données –Fermer le stream Écriture –Ouvrir un stream (ou créer un fichier) –Écrire des données tant qu’il y en a –Fermer le stream Établir un canal de communication Relâcher les ressources allouées Écrire ce qu’il est dans le tampon, et Relâcher les ressources allouées

Exemple: TP1 public static void main(String[] args) { ouvrir_fichier("liste_mots"); traiter_fichier(); fermer_fichier(); } public static void ouvrir_fichier(String nom) { try { input = new BufferedReader( new FileReader(nom)); } catch (IOException e) { System.err.println("Impossible d'ouvrir le fichier d'entree.\n" + e.toString()); System.exit(1); } public static void traiter_fichier() { String ligne; try { // catch EOFException ligne = input.readLine(); while (ligne != null) { System.out.println(ligne); ligne = input.readLine(); } public static void fermer_fichier() { try { input.close(); System.exit(0); } catch (IOException e) { System.err.println("Impossible de fermer les fichiers.\n" + e.toString()); }

Un autre exemple public void readFile() { FileReader fileReader = null; try { fileReader = new FileReader("input.txt"); int c = fileReader.read(); while (c != -1) { char d = ((char)c); c = fileReader.read(); } } catch (FileNotFoundException e) { System.out.println("File was not found"); } catch (IOException e) { System.out.println("Error reading from file"); } if (fileReader != null) { try { fileReader.close(); } catch (IOException e) { /* ignore */ } }

Deux unité de base Caractère (2 octets=16 bits) ou octet (8 bits) Deux hiérarchies de classe similaires (mais en parallèle)

Hiérarchies En haut des hiérarchies pour stream de caractères: 2 classes abstraites Reader java.lang.Object java.io.Reader Writer java.lang.Object java.io.Writer Implantent une partie des méthodes pour lire et écrire des caractère de 16 bits (2 octets)

Hiérarchie de Stream de caractère Les sous-classe de Reader simplepré-traitement Chaque sous-classe ajoute des méthodes

Hiérarchie de Stream de caractère Les sous-classe de Writer

Hiérarchies Byte Stream System.in

Hiérarchie de Byte Stream System.out System.err

Différence: caractère vs byte Reader: –int read() –int read(char cbuf[]) –int read(char cbuf[], int offset, int length) InputStream: –int read() –int read(byte cbuf[]) –int read(byte cbuf[], int offset, int length)

Utilisation de différentes classes En mémoire: –CharArrayReader, CharArrayWriter –ByteArrayInputStream, ByteArrayOutputStream –Lire/écrire dans un tableau de bytes –StringReader, StringWriter, StringBufferInputStream –Lire/écrire dans un String Pipe: –PipedReader, PipedWriter –PipedInputStream, PipedOutputStream –Relier la sortie d’un Stream comme une entrée d’un autre stream (pipeline)

Utilisation Fichier (*) –FileReader, FileWriter –FileInputStream, FileOutputStream –Lire/écrire dans un fichier Sérialisation –ObjectInputStream, ObjectOutputStream Conversion de données (*) –DataInputStream, DataOutputStream –Reconnaître les types de données primitifs Impression (*) –PrintWriter, PrintStream –Méthodes conviviales pour l’impression

Utilisation Buffer (Tampon) –BufferedReader, BufferedWriter –BufferedInputStream, BufferedOutputStream –Créer un tampon: accès plus efficace Filtering –FilterReader, FilterWriter –FilterInputStream, FilterOutputStream –Accepte un Stream, le filtre et ensuite passer à un autre Stream Convertir entre byte et caractère –InputStreamReader, OutputStreamWriter –Lire des bytes en caractère, ou écrire des caractère en byte

Exemple Utiliser FileReader et FileWriter Méthodes simples disponible: –int read(), int read(CharBuffer []), write(int),.. –Exemple: copier un fichier caractère par caractère (comme un int) import java.io.*; public class Copy { public static void main(String[] args) throws IOException { File inputFile = new File("farrago.txt"); File outputFile = new File("outagain.txt"); FileReader in = new FileReader(inputFile); FileWriter out = new FileWriter(outputFile); int c; while ((c = in.read()) != -1) out.write(c); in.close(); out.close(); } –Méthodes limitées Fin de fichier: -1

Augmenter les possibilités: wrap Créer un stream en se basant sur un autre: FileReader in = new FileReader(new File("farrago.txt")); Avantage: –Obtenir plus de méthodes Dans File: les méthodes pour gérer les fichier (delete(), getPath(), …) mais pas de méthode pour la lecture Dans FileReader: les méthodes de base pour la lecture –Un autre exemple: DataOutputStream out = new DataOutputStream( new FileOutputStream("invoice1.txt")); FileOutptuStream: écrire des bytes DataOutputStream: les méthodes pour les types de données de base: write(int), writeBoolean(boolean), writeChar(int), writeDouble(double), writeFloat(float), …

Pourquoi faire du wrapping? Les streams enrichis ont besoin d’un stream plus primitif dans son constructeur: –E.g. DataInputStream(InputStream in) DataOutputStream(OutputStream out)DataInputStreamInputStream DataOutputStreamOutputStream –Impossible de créer un stream directement d’un nom de fichier comme new DataOutputStream(“sortie”); –Besoin de faire du wrapping: New DataOutputStream(new FileOutputStream("sortie")) Les streams de base s’occupe des E/S de base, et les streams enrichies ajoutent d’autres possibilités Wrapping: réutiliser les méthodes de base, et ajouter d’autre méthodes

Hiérarchies

Sink stream Sink TypeCharacter StreamsByte Streams Memory CharArrayReader, CharArrayWriter StringReader, StringWriter ByteArrayInputStream, ByteArrayOutputStream StringBufferInputStream PipePipedReader, PipedWriter PipedInputStream, PipedOutputStream FileFileReader, FileWriter FileInputStream, FileOutputStream

Wrap dans quelle classe ? Dépend des méthodes dont on a besoin Quelques exemples –Lire ligne par ligne: Besoin de String readLine() (null à la fin du fichier) BufferedReader (sous classe de Reader) Traitement: –Lire une ligne (String) –Traiter cette ligne avec un Parsing (comme TP1) Constructeur: BufferedReader(Reader) new BufferedReader(new FileReader("fichier")) (FileReader est sous-classe de Reader – classe abstraite) –Écrire ligne par ligne BufferedWriter (sous-classe de Writer) write(String): écrire un String newLine(): insérer un changement de ligne Traitement: –Organiser une ligne comme String –Écrire la ligne

Wrap dans quelle classe ? Besoin: utiliser les méthodes comme dans System.out –write(int), … –print(…), println(…) Stream à utiliser: PrintWriter Constructeurs –PrintWriter(OutputStream out)PrintWriterOutputStream –PrintWriter(Writer out)PrintWriterWriter –new PrintWriter(new FileOutputStream("fichier")) –new PrintWriter(new FileWriter("fichier"))

Wrap dans quelle classe ? Besoin: écrire les données des types primitifs –writeChar(Char), writeFloat(float), … Stream à utiliser: DataOutputStream Constructeur: –DataOutputStream(OutputStream out)DataOutputStreamOutputStream –new DataOutputStream(new FileOutputStream("fichier"))

Interface: JFileChooser JFileChooser chooser = new JFileChooser(); FileReader in = null; if (chooser.showOpenDialog(null) == JFileChooser.APPROVE_OPTION) { File selectedFile = chooser.getSelectedFile(); reader = new FileReader(selectedFile);... }

Attention au format Stocker les données dans un fichier Mais aussi pouvoir les ressortir E.g. stocker le nom et la date de naissance: –GéraldTremblay SusanneRoy … Au moment de stocker, déterminer un format pour pouvoir les relire Façon simple: Gérald Tremblay Susanne Roy … –Lire prénom (jusqu’à l’espace), nom, date de naissance (il faut ensuite la décomposer)

Format Stocker en binaire ou en caractère? –Caractère: lisible (e.g. avec more, vi, etc.) –Binaire: transformer en code binaire: int: 4 octets Long: 8 octets char: 2 octet … –Valeur (entier) En caractère: (10 octets) En binaire: (4 octets) = 48* Binaire plus économique en espace Binaire = espace fixe (facilite la lecture)

Exemple en binaire Pour un compte bancaire: –No. de compte: entier –Montant: double Pour écrire un enregistrement (pour un compte) –writeInt(int) –writeDouble(double) –Classe: DataOutputStream Pour lire un enregistrement –readInt() –readDouble() –Classe: DataInputStream Penser aux écritures et aux lectures en même temps

DataInputStream et DataOutputStream Lire et écrire des données des types de base –readBoolean(), readInt(), readFloat, readChar(), readLine(); readUTF(), … –writeBoolean(boolean), writeInt(int), writeFloat(float), writeChar(char), writeChars(String), writeUTF(String), … –readUTF et writeUTF: Entier en binaire correspondant à la longueur du String + String Exemple: liste_mots prep sing sur pron_rel fem sing n masc sing outil non adv non n fem sing … Références:

Sérialiser Convertir un objet (avec une structure) en une suite de données dans un fichier Reconvertir du fichier en un objet Utilisation: avec ObjectOutputStream Employee[] staff = new Employee[3]; ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("test2.dat")); out.writeObject(staff); out.close();

Sérialiser Utilité de sérialisation –Stocker un objet dans un fichier –Créer une copie d’objet en mémoire –Transmettre un objet à distance Devient une transmission de String

Sérialiser Pour pouvoir sérialiser un objet: –sa classe doit implanter l’interface Serializable –Interface Serializable: Pas de méthode exigée Mais on peut réimplanter readObject() et writeObject() si on ne se contente pas de la version par défaut: defaultReadObject(), defaultWriteObject() private void writeObject(java.io.ObjectOutputStream out) throws IOException private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException –Beaucoup de classes existantes sont sérialisables (e.g. ArrayList)

Sérialiser: une classe sérialisable import java.io.*; import java.util.*; import java.util.logging.*; public class ExerciseSerializable { public static void main(String[] aArguments) { //create a Serializable List List quarks = new ArrayList(); quarks.add("up"); quarks.add("down"); quarks.add("strange"); quarks.add("charm"); quarks.add("top"); quarks.add("bottom"); try{ OutputStream file = new FileOutputStream( "quarks.ser" ); OutputStream buffer = new BufferedOutputStream( file ); output = new ObjectOutputStream( buffer ); output.writeObject(quarks); } catch(IOException ex){ fLogger.log(Level.SEVERE, "Cannot perform output.", ex); } finally{ try { if (output != null) { //flush and close "output" and its underlying streams output.close(); } catch (IOException ex ){ fLogger.log(Level.SEVERE, "Cannot close output stream.", ex); } ArrayList est sérialisable

Définir une clase sérialisable class Employee implements Serializable { public Employee(String n, double s, Date d) { name = n; salary = s; hireDate = d; } public Employee() {} public void raiseSalary(double byPercent) { salary *= 1 + byPercent / 100; } public int hireYear() { return hireDate.getYear(); } public void print() { System.out.println(name + " " + salary + " " + hireYear()); } private double salary; private String name; private Date hireDate; } class Manager extends Employee { public Manager(String n, double s, Date d, Employee e) { super(n, s, d); secretary = e; } public Manager() {} public void raiseSalary(double byPercent) { // add 1/2% bonus for every year of service Date today = new Date(); double bonus = 0.5 * (today.getYear() - hireYear()); super.raiseSalary(byPercent + bonus); } public void print() { super.print(); System.out.print("Secretary: "); if (secretary != null) secretary.print(); } private Employee secretary; }

Utiliser une classe sérialisable import java.io.*; import java.util.*; class ObjectRefTest { public static void main(String[] args) { try { Employee[] staff = new Employee[3]; Employee harry = new Employee ("Harry Hacker", 35000, new Date(1989,10,1)); staff[0] = harry; staff[1] = new Manager("Carl Cracker", 75000, new Date(1987,12,15), harry); staff[2] = new Manager("Tony Tester", 38000, new Date(1990,3,15), harry); ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("test2.dat")); out.writeObject(staff); out.close(); ObjectInputStream in = new ObjectInputStream( new FileInputStream ("test2.dat")); Employee[] newStaff = (Employee[])in.readObject(); for (int i = 0; i < newStaff.length; i++) newStaff[i].raiseSalary(100); for (int i = 0; i < newStaff.length; i++) newStaff[i].print(); } catch(Exception e) { e.printStackTrace(); System.exit(1); }

Sortie de sérialisation vi test2.dat: ^HEmployee~BÅ ^V 4 þ ^E Lisible par désérialisation (readObject()): Harry Hacker Carl Cracker Secretary: Harry Hacker Tony Tester Secretary: Harry Hacker

Accès séquentiel vs. aléatoire Séquentiel: Première donnée, suivante, … –Approprié pour traiter toutes les données Aléatoire (random): positionner à un endroit, lire les données à partir de cette position –Approprié pour sélectionner certaines données à traiter –Question importante: Comment déterminer la position correcte ?

RandomAccessFile Un Stream en format binaire Écrire et lire (selon l’ouverture) Possibilité de positionner avec seek(long) Exemple: file = new RandomAccessFile(filename, "rw"); file.seek(100); int accountNumber = file.readInt(); double balance = file.readDouble(); Référence:

RandomAccessFile Ouverture: file = new RandomAccessFile(filename, "rw"); Modes: r: lecture seulement rw: lecture et ecriture Mode

RandomAccessFile Lecture ou écriture –Sans seek: Position au début du fichier Écrire et lire à partir de cette position comme un accès séquentiel –seek(long) Positionner à la position (no. de bytes à partir du début) Lire ou écrire à partir de cette position

Position Comment déterminer la bonne position? –Solution simple: Chaque enregistrement = taille fixe Pour un enregistrement: déterminer son numéro seek(taille*no) –Solution plus complexe: Organiser un indexe Utiliser une table de hashage

Taille fixe pour un enregistrement 008: public class BankData 009: { 024: public void open(String filename) 025: throws IOException 026: { 027: if (file != null) file.close(); 028: file = new RandomAccessFile(filename, "rw"); 029: } 035: public int size() 036: throws IOException 037: { 038: return (int) (file.length() / RECORD_SIZE); 039: } 071: public int find(int accountNumber) 072: throws IOException 073: { 074: for (int i = 0; i < size(); i++) 075: { 076: file.seek(i * RECORD_SIZE); 077: int a = file.readInt(); 078: if (a == accountNumber) // Found a match 079: return i; 080: } 081: return -1; // No match in the entire file 082: } 056: public BankAccount read(int n) 057: throws IOException 058: { 059: file.seek(n * RECORD_SIZE); 060: int accountNumber = file.readInt(); 061: double balance = file.readDouble(); 062: return new BankAccount(accountNumber, balance); 063: } 089: public void write(int n, BankAccount account) 090: throws IOException 091: { 092: file.seek(n * RECORD_SIZE); 093: file.writeInt(account.getAccountNumber()); 094: file.writeDouble(account.getBalance()); 095: } 096: 097: private RandomAccessFile file; 098: 099: public static final int INT_SIZE = 4; 100: public static final int DOUBLE_SIZE = 8; 101: public static final int RECORD_SIZE 102: = INT_SIZE + DOUBLE_SIZE; 103: }

Accès dans RandomAccessFile Exploiter seek pour déterminer la position pour lire ou écrire un enregistrement –Séquentiel: lire chaque enregistrement à partir du début –Direct: déterminer une position selon une clé, et lire/écrire l’enregistrement Position = no. de compte * taille: –clé = no. de compte Position est déterminer selon une conversion avec une clé (e.g. code permanent GILB ) –Non numérique –Non compact: valeur non continue

Cas 1: Recherche binaire Les enregistrements sont stockés dans l’ordre croissant des clés Accès binaire (O(log(n)): –Chercher(clé, début, fin): Lire le milieu Si clé_milieu == clé, trouvé Si clé_milieu < clé, –Si (milieu – début) < 2, introuvable; –Sinon cherche(clé, début, milieur-1) Si clé_milieu > clé, –Si (fin – milieu) < 2, introuvable; –Sinon cherche(clé, milieu+1, fin)

Recherche binaire Fichier

Cas 2: table de hashage Table de hashage: déterminer une position pour chaque clé Fonction de hashage: clé entier Contraintes: –Le plus compacte possible (pas beaucoup de positions vides) –Le moins de conflit possible (2 clés – même position)

Exemple simple Transformer un code permanent en un entier: –VALB code –4 premiers caractères: A-Z: (1-26) 4 –2 chiffres: 01-31:1-31 –2 chiffres: 01-12, 5-62: 1-24 –2 chiffres: ( ): 0-90 –2 chiffres: 01-99: 1-99 Fonction1(clé) = concatener les codes –Compacte ? 00*** et 27***, **00*** et **32*** non utilisés Fonction2(clé) = code(L1)*…*code(L4)*code(jour)* code(mois)*code(année)*code(derniers_ch) –Conflit? VALB = VALB

Approche générale Valeur non conflictuelle (mais relativement compact) Déterminer la taille approximative du fichier souhaitée (taille) Valeur % primaire –Primaire est un nombre proche de la taille –E.g. < enregistrements: 10007, 10009, 10037, …12007, … –Prévoir plus large –Prévoir un mécanisme pour résoudre le conflit Aller à la suivante Rehashage: appliquer une autre fonction de hashage …

Cas 3: indexe Maintenir une structure d’indexe (clé= lettre + nombre) a b c … z 0pos …… 20 21pos 90 Clé= a21