Flux de Caractères et Sérialisation d'Objets en Java

Flux de Caractères

Les flux de Caractères traitent les données unité par unité en caractères, permettant uniquement la lecture de fichiers texte. Ils convertissent les octets lus en caractères à l'aide d'une table d'encodage. Les classes abstraites Reader et Writer servent de base, tandis que InputStreamReader et OutputStreamWriter sont des flux de conversion qui héritent de ces dernières pour effectuer la transformation des octets en caractères.

1. FileReader et FileWriter pour la lecture/écriture de fichiers

Méthodes courantes de FileReader Description
FileReader(String nomFichier) Constructeur spécifiant le fichier à lire
int read() Lit un caractère, retourne sa valeur de code ou -1 si fin de flux
int read(char[] tableau) Lit un tableau de caractères, retourne le nombre effectif de caractères lus
Méthodes courantes de FileWriter Description
FileWriter(String nomFichier, boolean ajout) Constructeur pour le fichier à écrire, avec option d'ajout ou d'écrasement
void write(int c) Écrit un caractère
void write(char[] tableau, int offset, int longueur) Écrit une portion d'un tableau de caractères

1.1 Lecture caractère par caractère


public class LectureSimple {
    public static void main(String[] args) throws IOException {
        FileReader lecteur = new FileReader("donnees.txt");
        FileWriter redacteur = new FileWriter("sortie.txt");
        int symbole;
        while ((symbole = lecteur.read()) != -1) {
            redacteur.write(symbole);
        }
        lecteur.close();
        redacteur.close();
    }
}

1.2 Lecture par tableau de caractères


public class LectureTableau {
    public static void main(String[] args) throws IOException {
        FileReader source = new FileReader("donnees.txt");
        FileWriter destination = new FileWriter("sortie.txt");
        int quantiteLue;
        char[] tampon = new char[1024];
        while ((quantiteLue = source.read(tampon)) != -1) {
            destination.write(tampon, 0, quantiteLue);
        }
        source.close();
        destination.close();
    }
}

2. Flux tamponnés pour caractères (flux d'emballage)

Méthodes courantes de BufferedReader Description
BufferedReader(Reader entree) Constructeur prenant un objet Reader
String readLine() Lit une ligne complète
Méthodes courantes de BufferedWriter Description
BufferedWriter(Writer sortie) Constructeur prenant un objet Writer
void write(String chaine) Écrit une chaîne de caractères
void newLine() Écrit un saut de ligne

2.1 Utilisation de BufferedReader et BufferedWriter

Ces flux d'emballage enveloppent les flux de nœuds FileReader et FileWriter pour améliorer l'efficacité via la lecture/écriture ligne par ligne. Le constructeur de FileWriter avec un booléen permet l'ajout au contenu existant sans écrasement. La méthode newLine() insère un saut de ligne dans le fichier.


public class TraitementLignes {
    public static void main(String[] args) throws IOException {
        FileReader lecteurBrut = new FileReader("entree.txt");
        FileWriter redacteurBrut = new FileWriter("sortie.txt", true);
        BufferedReader lecteurTampon = new BufferedReader(lecteurBrut);
        BufferedWriter redacteurTampon = new BufferedWriter(redacteurBrut);
        String ligne;
        while ((ligne = lecteurTampon.readLine()) != null) {
            redacteurTampon.write(ligne);
            redacteurTampon.newLine();
        }
        lecteurTampon.close();
        redacteurTampon.close();
    }
}

2.2 Lecture depuis la console avec BufferedReader


public class LectureConsole {
    public static void main(String[] args) throws IOException {
        BufferedReader entreeConsole = new BufferedReader(new InputStreamReader(System.in));
        System.out.println("Entrez une chaîne :");
        String saisie = entreeConsole.readLine();
        System.out.println("Saisie : " + saisie);
    }
}

Flux d'Octets pour Entrée/Sortie d'Objets

ObjectInputStream permet de lire des objets depuis un fichier, tandis qu'ObjectOutputStream les y écrit. Ces flux d'emballage s'appliquent aux flux do'ctets pour la sérialisation.

1. Besoin de la sérialisation d'objets

Les objets créés en mémoire sont éphémères et détruits à la fin du programme. La sérialisation persiste leurs données dans un fichier, permettant leur restauration ultérieure, comme pour sauvegarder les données d'utilisateurs lors de maintenances de serveurs.

2. Sérialisation et désérialisation d'objets

Sérialisation : Écriture des informations d'un objet dans un fichier via ObjectOutputStream.

Méthodes courantes de ObjectOutputStream Description
ObjectOutputStream(OutputStream sortie) Constructeur prenant un flux de sortie
writeObject(Object objet) Écrit un objet dans le fichier

Désérialisation : Lecture d'un objet depuis un fichier via ObjectInputStream.

Méthodes courantes de ObjectInputStream Description
ObjectInputStream(InputStream entree) Constructeur prenant un flux d'entrée
Object readObject() Lit et retorune un objet depuis le fichier

Pour sérialiser une classe personnalisée, elle doit implémenter l'interface Serializable, qui génère automatiquement un numéro de sérialisation unique. Ce numéro idnetifie la classe ; si la classe est modifiée, un nouveau numéro est généré, ce qui peut causer des erreurs lors de la désérialisation d'anciennes instances.


import java.io.Serializable;

public class Etudiant implements Serializable {
    private static final long serialVersionUID = 123456789L;
    private int code;
    private String nom;

    public Etudiant(int code, String nom) {
        this.code = code;
        this.nom = nom;
    }

    // Getters et setters omis pour concision
    @Override
    public String toString() {
        return "Etudiant{code=" + code + ", nom='" + nom + "'}";
    }
}


public class SerialisationDemo {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        Etudiant eleve = new Etudiant(101, "Alice");

        // Sérialisation
        FileOutputStream fluxSortie = new FileOutputStream("etudiant.bin");
        ObjectOutputStream sortieObjet = new ObjectOutputStream(fluxSortie);
        sortieObjet.writeObject(eleve);
        sortieObjet.close();

        // Désérialisation
        FileInputStream fluxEntree = new FileInputStream("etudiant.bin");
        ObjectInputStream entreeObjet = new ObjectInputStream(fluxEntree);
        Etudiant restaure = (Etudiant) entreeObjet.readObject();
        System.out.println(restaure);
        entreeObjet.close();
    }
}

Pour éviter les erreurs dues aux modifications de classe, déclarez explicitement un serialVersionUID. Ainsi, le numéro reste constant malgré les changements dans la structure de la classe. Notez que si la classe est modifiée, une nouvelle sérialisation est nécessaire pour refléter les modifications.

3. Configuration d'IDEA pour le serialVersionUID

Dans les versions récentes d'IDEA, configurez les paramètres pour générer automatiquement un serialVersionUID lorsque l'interface Serializable est implémentée. Placez le curseur sur le nom de classe pour afficher l'option. Cela garantit la compatibilité lors des sérialisations ultérieures, sous réserve de re-sérialiser les objets après des modifications de classe.

Étiquettes: Java IOStreams CharacterStreams FileReader FileWriter

Publié le 20 juillet à 21h44