fichier et stream d entr e sortie
Download
Skip this Video
Download Presentation
Fichier et Stream d’Entrée-Sortie

Loading in 2 Seconds...

play fullscreen
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^@^@xp^@^@^@^Csr^@^HEmployee~BÅ<89>^V<99>q=^B^@^CD^@^FsalaryL^@^HhireDatet^@^PLjava/util/Date;L^@^Dnamet^@^RLjava/lang/String;[email protected]á^W^@^@^@^@^@sr^@^Njava.util.Datehj<81>^AKYt^Y^C^@^@xpw^H^@^@7^Y×<8c>4<80>xt^@^LHarry Hackersr^@^GManager^U<9d><93>þ<8f>Íq^[^B^@^AL ^@secretaryt^@LEmployee;xq^@~^@^[email protected]òO<80>^@^@^@^@sq^@~^@^Fw^H^@^@7^L¥@t<80>xt^@^LCarl Crackerq^@~^@^Esq^@~^@@â <8e>^@^@^@^@^@sq^@~^@^Fw^H^@^@7^])^N<92>^@xt^@^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