Fichier et Stream dEntreSortie IFT 1025 Programmation 2
- Slides: 50
Fichier et Stream d’Entrée-Sortie IFT 1025, 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 CPU • Traitement fichier Mémoire vive tampon
Fichier en Java • Stream: une suite de données (octets ou caractères)
Opérations typiques • Lecture: Établir un canal de communication – Ouvrir un stream – Lire tant qu’il y a des données Relâcher les – Fermer le stream • Écriture ressources allouées – Ouvrir un stream (ou créer un fichier) – Écrire des données tant qu’il y en a Écrire ce qu’il est dans le – Fermer le stream tampon, et Relâcher les ressources allouées
Exemple: TP 1 public static void main(String[] args) { public static void traiter_fichier() { String ligne; ouvrir_fichier("liste_mots"); traiter_fichier(); try { // catch EOFException ligne = input. read. Line(); while (ligne != null) { System. out. println(ligne); ligne = input. read. Line(); } fermer_fichier(); } public static void ouvrir_fichier(String nom) { try { input = new Buffered. Reader( new File. Reader(nom)); } catch (IOException e) { System. err. println("Impossible d'ouvrir le fichier d'entree. n" + e. to. String()); System. exit(1); } } public static void fermer_fichier() { try { input. close(); System. exit(0); } catch (IOException e) { System. err. println("Impossible de fermer les fichiers. n" + e. to. String()); } }
Un autre exemple public void read. File() { File. Reader file. Reader = null; try { file. Reader = new File. Reader("input. txt"); int c = file. Reader. read(); while (c != -1) { char d = ((char)c); c = file. Reader. read(); } } catch (File. Not. Found. Exception e) { System. out. println("File was not found"); } catch (IOException e) { System. out. println("Error reading from file"); } if (file. Reader != null) { try { file. Reader. 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 simple pré-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 offset, int length) • Input. Stream: – int read() – int read(byte cbuf[], int offset, int length)
Utilisation de différentes classes • En mémoire: – Char. Array. Reader, Char. Array. Writer – Byte. Array. Input. Stream, Byte. Array. Output. Stream – Lire/écrire dans un tableau de bytes – String. Reader, String. Writer, String. Buffer. Input. Stream – Lire/écrire dans un String • Pipe: – Piped. Reader, Piped. Writer – Piped. Input. Stream, Piped. Output. Stream – Relier la sortie d’un Stream comme une entrée d’un autre stream (pipeline)
Utilisation • Fichier (*) – File. Reader, File. Writer – File. Input. Stream, File. Output. Stream – Lire/écrire dans un fichier • Sérialisation – Object. Input. Stream, Object. Output. Stream • Conversion de données (*) – Data. Input. Stream, Data. Output. Stream – Reconnaître les types de données primitifs • Impression (*) – Print. Writer, Print. Stream – Méthodes conviviales pour l’impression
Utilisation • Buffer (Tampon) – Buffered. Reader, Buffered. Writer – Buffered. Input. Stream, Buffered. Output. Stream – Créer un tampon: accès plus efficace • Filtering – Filter. Reader, Filter. Writer – Filter. Input. Stream, Filter. Output. Stream – Accepte un Stream, le filtre et ensuite passer à un autre Stream • Convertir entre byte et caractère – Input. Stream. Reader, Output. Stream. Writer – Lire des bytes en caractère, ou écrire des caractère en byte
Exemple • • Utiliser File. Reader et File. Writer Méthodes simples disponible: – int read(), int read(Char. Buffer []), 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 input. File = new File("farrago. txt"); File output. File = new File("outagain. txt"); File. Reader in = new File. Reader(input. File); File. Writer out = new File. Writer(output. File); 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: File. Reader in = new File. Reader(new File("farrago. txt")); • Avantage: – Obtenir plus de méthodes • Dans File: les méthodes pour gérer les fichier (delete(), get. Path(), …) mais pas de méthode pour la lecture • Dans File. Reader: les méthodes de base pour la lecture – Un autre exemple: Data. Output. Stream out = new Data. Output. Stream( new File. Output. Stream("invoice 1. txt")); • File. Outptu. Stream: écrire des bytes • Data. Output. Stream: les méthodes pour les types de données de base: write(int), write. Boolean(boolean), write. Char(int), write. Double(double), write. Float(float), …
Pourquoi faire du wrapping? • Les streams enrichis ont besoin d’un stream plus primitif dans son constructeur: – E. g. Data. Input. Stream(Input. Stream in) Data. Output. Stream(Output. Stream out) – Impossible de créer un stream directement d’un nom de fichier comme new Data. Output. Stream(“sortie”); – Besoin de faire du wrapping: • New Data. Output. Stream(new File. Output. Stream("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 Type Character Streams Byte Streams Memory Char. Array. Reader, Char. Array. Writer Byte. Array. Input. Stream, Byte. Array. Output. Stream String. Reader, String. Writer String. Buffer. Input. Stream Piped. Reader, Piped. Writer Piped. Input. Stream, Piped. Output. Stream File. Reader, File. Writer File. Input. Stream, File. Output. Stream
Wrap dans quelle classe ? • Dépend des méthodes dont on a besoin • Quelques exemples – Lire ligne par ligne: • Besoin de String read. Line() (null à la fin du fichier) • Buffered. Reader (sous classe de Reader) • Traitement: – Lire une ligne (String) – Traiter cette ligne avec un Parsing (comme TP 1) • Constructeur: Buffered. Reader(Reader) • new Buffered. Reader(new File. Reader("fichier")) (File. Reader est sous-classe de Reader – classe abstraite) – Écrire ligne par ligne • • Buffered. Writer (sous-classe de Writer) write(String): écrire un String new. Line(): 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: Print. Writer • Constructeurs – – Print. Writer(Output. Stream out) Print. Writer(Writer out) new Print. Writer(new File. Output. Stream("fichier")) new Print. Writer(new File. Writer("fichier"))
Wrap dans quelle classe ? • Besoin: écrire les données des types primitifs – write. Char(Char), write. Float(float), … • Stream à utiliser: Data. Output. Stream • Constructeur: – Data. Output. Stream(Output. Stream out) – new Data. Output. Stream(new File. Output. Stream("fichier"))
Interface: JFile. Chooser chooser = new JFile. Chooser(); File. Reader in = null; if (chooser. show. Open. Dialog(null) == JFile. Chooser. APPROVE_OPTION) { File selected. File = chooser. get. Selected. File(); reader = new File. Reader(selected. File); . . . }
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érald. Tremblay 19500101 Susanne. Roy 19800406… • Au moment de stocker, déterminer un format pour pouvoir les relire Façon simple: Gérald Tremblay 19500101 Susanne Roy 19800406… – 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 12345 (entier) • • En caractère: 12345 (10 octets) En binaire: 0 0 48 57 (4 octets) = 48*256+57 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) – write. Int(int) – write. Double(double) – Classe: Data. Output. Stream • Pour lire un enregistrement – read. Int() – read. Double() – Classe: Data. Input. Stream • Penser aux écritures et aux lectures en même temps
Data. Input. Stream et Data. Output. Stream • Lire et écrire des données des types de base – read. Boolean(), read. Int(), read. Float, read. Char(), read. Line(); read. UTF(), … – write. Boolean(boolean), write. Int(int), write. Float(float), write. Char(char), write. Chars(String), write. UTF(String), … – read. UTF et write. UTF: • Entier en binaire correspondant à la longueur du String + String • Exemple: liste_mots ^@&sur prep sing sur rel^@(laquelle pron_rel fem sing ^@&systeme n masc sing outil ^@ non adv non rel^@$echeance n fem sing temps^@^^entite … Références: http: //java. sun. com/j 2 se/1. 5. 0/docs/api/java/io/Data. Output. Stream. html http: //java. sun. com/j 2 se/1. 5. 0/docs/api/java/io/Data. Input. Stream. html
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 Object. Output. Stream Employee[] staff = new Employee[3]; Object. Output. Stream out = new Object. Output. Stream(new File. Output. Stream("test 2. dat")); out. write. Object(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 read. Object() et write. Object() si on ne se contente pas de la version par défaut: default. Read. Object(), default. Write. Object() • private void write. Object(java. io. Object. Output. Stream out) throws IOException • private void read. Object(java. io. Object. Input. Stream in) throws IOException, Class. Not. Found. Exception – Beaucoup de classes existantes sont sérialisables (e. g. Array. List)
Sérialiser: une classe sérialisable import java. io. *; import java. util. logging. *; try{ Output. Stream file = new File. Output. Stream( "quarks. ser" ); Output. Stream buffer = new Buffered. Output. Stream( file ); output = new Object. Output. Stream( buffer ); output. write. Object(quarks); } catch(IOException ex){ public static void main(String[] a. Arguments) { f. Logger. log(Level. SEVERE, "Cannot perform output. ", ex); //create a Serializable List } List quarks = new Array. List(); finally{ quarks. add("up"); try { quarks. add("down"); if (output != null) { quarks. add("strange"); //flush and close "output" and its underlying streams quarks. add("charm"); output. close(); quarks. add("top"); } quarks. add("bottom"); } catch (IOException ex ){ f. Logger. log(Level. SEVERE, "Cannot close output stream. ", ex); } } Array. List est sérialisable public class Exercise. Serializable {
Définir une clase sérialisable class Employee implements Serializable { public Employee(String n, double s, Date d) { name = n; salary = s; hire. Date = d; } class Manager extends Employee { public Manager(String n, double s, Date d, Employee e) { super(n, s, d); secretary = e; } public Employee() {} public Manager() {} public void raise. Salary(double by. Percent) { salary *= 1 + by. Percent / 100; } public void raise. Salary(double by. Percent) { // add 1/2% bonus for every year of service Date today = new Date(); double bonus = 0. 5 * (today. get. Year() - hire. Year()); super. raise. Salary(by. Percent + bonus); } public int hire. Year() { return hire. Date. get. Year(); } public void print() { System. out. println(name + " " + salary + " " + hire. Year()); } private double salary; private String name; private Date hire. Date; } 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 Object. Ref. Test { 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); Object. Output. Stream out = new Object. Output. Stream(new File. Output. Stream("test 2. dat")); out. write. Object(staff); out. close(); Object. Input. Stream in = new Object. Input. Stream( new File. Input. Stream ("test 2. dat")); Employee[] new. Staff = (Employee[])in. read. Object(); for (int i = 0; i < new. Staff. length; i++) new. Staff[i]. raise. Salary(100); for (int i = 0; i < new. Staff. length; i++) new. Staff[i]. print(); } catch(Exception e) { e. print. Stack. Trace(); System. exit(1); } } }
Sortie de sérialisation vi test 2. dat: ¬í^@^Eur^@^K[LEmployee; ü¿ 6^QÅ<91>^QÇ^B^@^@xp^@^@^@^Csr^@ ^HEmployee~BÅ<89>^V<99>q=^B^@^CD^@^Fsalary. L^@^Hhire. Datet^@^ PLjava/util/Date; L^@^Dnamet^@^RLjava/lang/String; xp@á^W^@^@ ^@sr^@^Njava. util. Datehj<81>^AKYt^Y^C^@^@xpw^H^@^@7^Y×<8 c>4< 80>xt^@^LHarry Hackersr^@^GManager^U<9 d><93>þ<8 f>Íq^[^B^@^AL ^@secretaryt^@LEmployee; xq^@~^@^B@òO<80>^@^@sq^@~^@ ^Fw^H^@^@7^L¥@t<80>xt^@^LCarl Crackerq^@~^@^Esq^@~^@@â <8 e>^@^@^@sq^@~^@^Fw^H^@^@7^])^N<92>^@xt^@^KTony Testerq^@~^@ ^E Lisible par désérialisation (read. Object()): Harry Hacker 70000. 0 1989 Carl Cracker -555750. 0 1988 Secretary: Harry Hacker 70000. 0 1989 Tony Tester -281960. 0 1990 Secretary: Harry Hacker 70000. 0 1989
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 ?
Random. Access. File • • Un Stream en format binaire Écrire et lire (selon l’ouverture) Possibilité de positionner avec seek(long) Exemple: file = new Random. Access. File(filename, "rw"); file. seek(100); int account. Number = file. read. Int(); double balance = file. read. Double(); Référence: http: //java. sun. com/j 2 se/1. 4. 2/docs/api/java/io/Random. Access. File. html
Random. Access. File • Ouverture: file = new Random. Access. File(filename, "rw"); Modes: r: lecture seulement rw: lecture et ecriture Mode
Random. Access. File • 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 Bank. Data 009: { 024: public void open(String filename) 025: throws IOException 026: { 027: if (file != null) file. close(); 028: file = new Random. Access. File(filename, "rw"); 029: } 035: public int size() 036: throws IOException 037: { 038: return (int) (file. length() / RECORD_SIZE); 039: } 071: public int find(int account. Number) 072: throws IOException 073: { 074: for (int i = 0; i < size(); i++) 075: { 076: file. seek(i * RECORD_SIZE); 077: int a = file. read. Int(); 078: if (a == account. Number) // Found a match 079: return i; 080: } 081: return -1; // No match in the entire file 082: } 056: public Bank. Account read(int n) 057: throws IOException 058: { 059: file. seek(n * RECORD_SIZE); 060: int account. Number = file. read. Int(); 061: double balance = file. read. Double(); 062: return new Bank. Account(account. Number, balance); 063: } 089: public void write(int n, Bank. Account account) 090: throws IOException 091: { 092: file. seek(n * RECORD_SIZE); 093: file. write. Int(account. get. Account. Number()); 094: file. write. Double(account. get. Balance()); 095: } 096: 097: private Random. Access. File 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 Random. Access. File • 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 76022304) – 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 1 3 6 8 10 16 20
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 23027502 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: 50 -40 (1950 -2040): 0 -90 – 2 chiffres: 01 -99: 1 -99 • Fonction 1(clé) = concatener les codes – Compacte ? 00*** et 27***, **00*** et **32*** non utilisés • Fonction 2(clé) = code(L 1)*…*code(L 4)*code(jour)* code(mois)*code(année)*code(derniers_ch) – Conflit? VALB 23027502 = VALB 23017504
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. <10 000 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) 0 Clé= a 21 a b c … … 20 21 pos 0 10 20 … 90 z 90 pos
- Ift 1025
- Ift 1025
- Ift1025
- Ift 1025
- Ift 1025
- Ift 1025
- Ift 1025
- Ift 1025
- Fiche personnelle
- Un fichier fourni
- Analyse fichier log
- Differentiate byte stream and character stream
- Shapes of molecules a level chemistry
- Reactions of aldehydes and ketones chemsheets answers
- Mit 1025
- 1025 ce
- Php
- Scheme langage
- Typedef
- Théorème de dualité en programmation linéaire
- Robot abb programmation
- Tableau go
- Programmation lineaire
- Aspect java
- Programmation agile
- Role ladder
- Programmation
- Michel bierlaire
- Programmation web avancée
- Problème de transport en programmation linéaire
- Programmation annuelle école de football
- Programmation
- Programmation lineaire
- Programmation procédurale vs orienté objet
- Ace ift model cardiorespiratory training
- çift burgulu kablo
- Ift 6261
- Ace ift model
- Ift 3355
- Ace ift model cardiorespiratory
- Victor ostromoukhov
- Ift 3295
- Ift-2102
- Ift nc
- Ift 6261
- Ift
- Ift 3355
- Ift2505
- Ift rosenheim
- Bracketer
- Function health fitness performance continuum