Fichier et stream d entr e sortie
Download
1 / 50

Fichier et Stream d Entr e-Sortie - PowerPoint PPT Presentation


  • 138 Views
  • Uploaded on

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.

loader
I am the owner, or an agent authorized to act on behalf of the owner, of the copyrighted work described.
capcha
Download Presentation

PowerPoint Slideshow about 'Fichier et Stream d Entr e-Sortie' - brooke


An Image/Link below is provided (as is) to download presentation

Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.


- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -
Presentation Transcript
Fichier et stream d entr e sortie

Fichier et Stream d’Entrée-Sortie

IFT1025, Programmation 2

Jian-Yun Nie


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

CPU

fichier

Mémoire vive

tampon


Fichier en java
Fichier en Java

  • Stream: une suite de données (octets ou caractères)


Op rations typiques
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());

}

}

Exemple: TP1


Un autre exemple
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
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
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
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 re1
Hiérarchie de Stream de caractère

  • Les sous-classe de Writer



Hi rarchie de byte stream
Hiérarchie de Byte Stream

System.out

System.err


Diff rence caract re vs byte
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
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
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


Utilisation1
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
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
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
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)

    • 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




Wrap dans quelle classe
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 classe1
Wrap dans quelle classe ?

  • Besoin: utiliser les méthodes comme dans System.out

    • write(int), …

    • print(…), println(…)

  • Stream à utiliser: PrintWriter

  • Constructeurs

    • PrintWriter(OutputStream out)

    • PrintWriter(Writer out)

    • new PrintWriter(new FileOutputStream("fichier"))

    • new PrintWriter(new FileWriter("fichier"))


Wrap dans quelle classe2
Wrap dans quelle classe ?

  • Besoin: écrire les données des types primitifs

    • writeChar(Char), writeFloat(float), …

  • Stream à utiliser: DataOutputStream

  • Constructeur:

    • DataOutputStream(OutputStream out)

    • new DataOutputStream(new FileOutputStream("fichier"))


Interface jfilechooser
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
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éraldTremblay19500101SusanneRoy19800406…

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

        ^@&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/j2se/1.5.0/docs/api/java/io/DataOutputStream.html

        http://java.sun.com/j2se/1.5.0/docs/api/java/io/DataInputStream.html


S rialiser
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 rialiser1
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 rialiser2
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);

}

}

Sérialiser: une classe sérialisable

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;

}

Définir une clase sérialisable


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);

}

}

}

Utiliser une classe sérialisable


Sortie de s rialisation
Sortie de sérialisation

vi test2.dat:

¬í^@^Eur^@^K[LEmployee;ü¿6^QÅ<91>^QÇ^B^@[email protected]^@^@^@^Csr^@^HEmployee~BÅ<89>^V<99>q=^B^@^CD^@^FsalaryL^@^HhireDatet^@^PLjava/util/Date;L^@^Dnamet^@^RLjava/lang/String;[email protected]^W^@^@^@^@[email protected]^@^Njava.util.Datehj<81>^AKYt^Y^C^@[email protected]^H^@[email protected]^Y×<8c>4<80>xt^@^LHarry Hackersr^@^GManager^U<9d><93>þ<8f>Íq^[^B^@^AL [email protected][email protected];xq^@~^@[email protected]<80>^@^@^@[email protected]^@~^@^Fw^H^@[email protected][email protected]<80>xt^@^LCarl Crackerq^@~^@^Esq^@~^@@â <8e>^@^@^@^@[email protected]^@~^@^Fw^H^@[email protected]^])^N<92>[email protected]^@^KTony Testerq^@~^@ ^E

Lisible par désérialisation (readObject()):

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

    http://java.sun.com/j2se/1.4.2/docs/api/java/io/RandomAccessFile.html


Randomaccessfile1
RandomAccessFile

  • Ouverture:

    file = new RandomAccessFile(filename, "rw");

    Modes:

    r: lecture seulement

    rw: lecture et ecriture

Mode


Randomaccessfile2
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
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: }

Taille fixe pour un enregistrement


Acc s dans randomaccessfile
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 GILB76022304)

        • Non numérique

        • Non compact: valeur non continue


Cas 1 recherche binaire
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)



Cas 2 table de hashage
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
Exemple simple

  • Transformer un code permanent en un entier:

    • VALB23027502 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

  • 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? VALB23027502 = VALB23017504


Approche g n rale
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
Cas 3: indexe

  • Maintenir une structure d’indexe (clé= lettre + nombre)

Clé=a21


ad