IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
logo

FAQ Fichiers, flux et réseauxConsultez toutes les FAQ

Nombre d'auteurs : 15, nombre de questions : 95, dernière mise à jour : 21 mars 2016  Ajouter une question

 

Cette FAQ a été réalisée à partir des questions fréquemment posées sur le forum Java de http://java.developpez.com ainsi que l'expérience personnelle des auteurs.

Nous tenons à souligner que cette FAQ ne garantit en aucun cas que les informations qu'elle propose sont correctes. Les auteurs font leur maximum, mais l'erreur est humaine. Cette FAQ ne prétend pas non plus être complète. Si vous trouvez une erreur, ou que vous souhaitez nous aider en devenant rédacteur, lisez ceci.

Sur ce, nous vous souhaitons une bonne lecture.

SommaireEntrées et sorties (28)
précédent sommaire suivant
 

Dans l'API Java, vous avez quatre façons distinctes, mais complémentaires de manipuler les entrées sorties.

Les flux
Les flux, qui font partie de l'API Java classique, permettent de lire et d’écrire des ensembles séquentiels d'octets qui peuvent provenir de fichiers, sockets, périphériques, etc. On les utilise, par exemple, pour lire et écrire des fichiers binaires (puisqu'on manipule des octets).

Les Reader et Writer
Dans l'API Java classique, ces classes sont destinées à manipuler des flux de caractères (des ensembles séquentiels de caractères) qui sont une dérivation spécialisée des flux d'octets et qui peuvent provenir de fichiers, sockets, périphériques, etc. On les utilise, par exemple, pour lire et écrire des fichiers texte (puisqu'on manipule des caractères).

La classe RandomAccessFile
Dans l'API Java classique, cette classe permet d'effectuer des opérations de lecture/écriture en accès direct sur un fichier. On l'utilise généralement pour lire et écrire des fichiers binaires.

Les canaux et les tampons
Dans NIO, ces objets permettent d’effectuer des opérations de lecture/écriture asynchrones (non bloquantes) sur des fichiers ou des sockets via des tampons mémoire. Les canaux permettent également de manipuler plus aisément des fichiers de grande taille. On les utilise généralement pour lire et écrire des fichiers binaires.

Note : le patron de conception décorateur est largement utilisé par les flux, les Reader, les Writer ce qui explique le nombre important de classes disponibles dans l'API.

Mis à jour le 16 août 2015 bouye

Dans l'API Java classique, un flux ou flux d’entrée/sortie (stream, I/O stream) est une entité qui permet de lire ou d’écrire une suite séquentielle d'octets. Les flux offrent une forme d'abstraction qui permet de manipuler des suites d'octets de manière unique, indépendante de la nature de la sortie ou de la source. On distingue les flux d’entrée (input stream) qui permettent de lire une suite séquentielle d'octets et les flux de sortie (output stream) qui permettent d’écrire une suite séquentielle d'octets. L'API contient plusieurs classes spécialisées permettant de manipuler des flux attachés à telle ou telle ressource ou de composer des flux entre eux (i.e. : ByteArrayInputStream, FileInputStream, DataInputStream, etc.). La plupart des opérations de lecture ou d’écriture sur les flux sont susceptibles de générer des exceptions de type IOException en cas d'erreur.

De par leur nature, les flux sont souvent attachés à des ressources natives (fichier, socket, etc.) qui doivent être libérées lorsque vous avez fini d'utiliser le flux. Vous devez donc invoquer leur méthode close() lorsque vous avez fini de les manipuler. Les flux implémentant l'interface AutoClosable, il est ainsi possible de les utiliser dans une construction try-with-resources qui fermera automatiquement le flux en fin de bloc.

Flux d’entrée
Ce type de flux permet de lire de façon identique des octets provenant d'un fichier, d'une socket réseau, d'un tableau d'octets en mémoire ou d'un port physique ou un périphérique, etc. Ces flux héritent de la classe java.io.InputStream.

Par exemple, pour lire le contenu d'un fichier avec l'API Java classique, on fera :

Code Java : Sélectionner tout
1
2
3
4
try (InputStream input = new FileInputStream("fichier.txt") { 
    // Lecture du flux. 
    [...] 
}

Et avec NIO2, on fera :

Code Java : Sélectionner tout
1
2
3
4
try (InputStream input = Files.newInputStream(Paths.get("fichier.txt")) { 
    // Lecture du flux. 
    [...] 
}

Flux de sortie
Ce type de flux permet d’écrire de façon identique des octets dans un fichier, une socket réseau, un tableau d'octets en mémoire ou sur un port physique ou périphérique, etc. Ces flux héritent de la classe java.io.OutputStream.

Par exemple, pour écrire dans un fichier avec l'API Java classique, on fera :

Code Java : Sélectionner tout
1
2
3
4
try (OutputStream output = new FileOutputStream("fichier.txt") { 
    // Écriture du flux. 
    [...] 
}

Et avec NIO2, on fera :

Code Java : Sélectionner tout
1
2
3
4
try (OutputStream output = Files.newOutputStream(Paths.get("fichier.txt")) { 
    // Écriture du flux. 
    [...] 
}

Mis à jour le 13 août 2015 bouye

Le patron de conception décorateur est largement utilisé par les flux ; certaines classes sont donc destinées à ajouter des nouveaux comportements et de nouvelles fonctionnalités aux flux d’entrée de base. Voici quelques-unes des classes de flux d’entrées que vous serez amenés à manipuler le plus souvent :

  • javax.sound.sampled.AudioInputStream - décore un flux d’entrée pour permettre d'y lire du son ;
  • java.io.ByteArrayInputStream - permet de manipuler un tableau d'octets (byte[]) comme un flux d’entrée ;
  • java.io.FileInputStream - permet d'ouvrir un flux d’entrée sur un fichier ;
  • java.io.FilterInputStream - classe de base pour tous les décorateurs permettant de filtrer le contenu du flux d’entrée :
    • java.io.BufferedInputStream - décore un flux d’entrée en lui associant un tampon mémoire,
    • java.io.DataInputStream - décore un flux d’entrée de manière à pouvoir y lire des types Java primitifs,
    • javax.swing.ProgressMonitorInputStream - décore un flux d’entrée de manière à pouvoir afficher une boite de dialogue de progression de lecture dans une interface Swing ;
  • java.io.ObjectInputStream - décore un autre flux d’entrée pour permettre de désérialiser un objet ;
  • java.io.PipedInputStream - permet de connecter un flux de sortie PipedOutputStream sur un flux d’entrée ;
  • java.io.SequenceInputStream - permet d'effectuer une concaténation logique de deux flux d’entrée.

Mis à jour le 16 août 2015 bouye

Le patron de conception décorateur est largement utilisé par les flux ; certaines classes sont donc destinées à ajouter des nouveaux comportements et de nouvelles fonctionnalités aux flux de sortie de base. Voici quelques-unes des classes de flux de sortie que vous serez amenés à manipuler le plus souvent :

  • java.io.ByteArrayOutputStream - permet de manipuler un tableau d'octets (byte[]) comme un flux de sortie ;
  • java.io.FileArrayOutputStream - permet d'ouvrir un flux de sortie vers un fichier ;
  • java.io.FilterOutputStream - classe de base pour tous les décorateurs permettant de filtrer le contenu du flux d’entrée :
    • java.io.BufferedOutputStream - décore un flux de sortie en lui associant un tampon mémoire,
    • java.io.DataOutputStream - décore un flux de sortie de manière à pouvoir y écrire des types Java primitifs,
    • java.io.PrintStream - décore un flux de sortie de manière à pouvoir utiliser des méthodes de formatage de chaines de caractères ;
  • java.io.ObjectOutputStream - décore un autre flux de sortie pour permettre de sérialiser un objet ;
  • java.io.java.io.PipedOutputStream - permet de connecter un flux d’entrée PipedInputStream sur un flux de sortie.

Mis à jour le 16 août 2015 bouye

Dans l'API Java classique, les objets Reader (liseuse) et Writer (machine à écrire, producteur de texte) permettent de manipuler plus aisément des flux contenant des caractères (character stream), par exemple : des fichiers texte ou l’entrée et la sortie de la console, chaine de caractères en mémoire. Ces classes offrent une abstraction permettant de s'affranchir du flux d'octets sur lequel repose le flux de caractères. Ces classes sont les bases de tout un ensemble de sous-classes spécialisées (ex. : liseuse de fichiers, liseuse de flux, liseuse de lignes, liseuse avec tampon, etc.) qu'il est possible de composer entre elles pour manipuler la source ou la destination sous-jacente de manière efficace. La plupart des opérations de lecture ou d’écriture sur les liseuses et les producteurs sont susceptibles de générer des exceptions de type IOException en cas d'erreur.

De par leur nature, les readers et les writers sont attachés à des flux de caractères qui empaquettent eux-mêmes des flux d'octets qui sont donc liés à des ressources natives (fichiers, sockets, etc.) qui doivent être libérées lorsque vous avez fini d'utiliser le flux. Vous devez donc invoquer leur méthode close() lorsque vous avez fini de les manipuler. Les readers et writers implémentent l'interface AutoClosable, il est ainsi possible de les utiliser dans une construction try-with-resources qui fermera automatiquement la liseuse ou le producteur en fin de bloc.

Reader
La classe java.io.Reader ainsi que ses classes dérivées spécialisées permettent de lire le contenu d'un flux séquentiel de caractères. Quand vous lisez le contenu d'un reader, ce dernier va, en fonction de l'encodage choisi, interpréter les octets contenus dans le flux d’entrée sous-jacent pour les convertir en caractères.

Par exemple, pour lire le contenu d'un fichier texte avec l'API Java classique, on fera :

Code Java : Sélectionner tout
1
2
3
4
try (LineNumberReader reader = new LineNumberReader(new FileReader("fichier.txt"))) { 
    // Lecture du fichier texte. 
    [...] 
}

Et avec NIO2, on fera :

Code Java : Sélectionner tout
1
2
3
4
try (LineNumberReader reader = new LineNumberReader(Files.newBufferedReader(Paths.get("fichier.txt")))) { 
    // Lecture du fichier texte. 
    [...] 
}

Writer
La classe java.io.Writer ainsi que ses classes dérivées spécialisées permettent d’écrire dans un flux séquentiel de caractères. Quand vous écrivez du contenu sur un writer, ce dernier va, en fonction de l'encodage choisi, convertir les caractères écrits en octets qui seront transmis au flux de sortie sous-jacent.

Par exemple, pour écrire le contenu d'un fichier texte avec l'API Java classique, on fera :

Code Java : Sélectionner tout
1
2
3
4
try (PrintWriter writer = new PrintWriter(new FileWriter("fichier.txt"))) { 
    // Écriture du fichier texte. 
    [...] 
}

Et avec NIO2, on fera :

Code Java : Sélectionner tout
1
2
3
4
try (PrintWriter writer = new PrintWriter(Files.newBufferedWriter(Paths.get("fichier.txt")))) { 
    // Écriture du fichier texte. 
    [...] 
}

Mis à jour le 13 août 2015 bouye

Le patron de conception décorateur est largement utilisé par les liseuses ; certaines classes sont donc destinées à ajouter des nouveaux comportements et de nouvelles fonctionnalités aux readers de base. Voici quelques-unes des classes de liseuses que vous serez amenés à manipuler le plus souvent :

  • java.io.BufferedReader - classe de base pour tous les décorateurs permettant d'associer un tampon mémoire au contenu de la liseuse :
    • java.io.LineNumberReader - décorateur qui garde trace du nombre de lignes de texte lues ;
  • java.io.CharArrayReader - permet de manipuler un tableau de caractères (char[]) comme une liseuse ;
  • java.io.InputStreamReader - empaquète un flux d’entrée (InputStream) dans une liseuse :
    • java.io.FileReader - empaquète un flux d’entrée sur un fichier (FileInputStream) dans une liseuse ;
  • java.io.PipedReader - permet de connecter un producteur PipedWriter sur une liseuse ;
  • java.io.StringReader - permet de manipuler une chaine de caractères (String) comme une liseuse.

Mis à jour le 17 août 2015 bouye

Le patron de conception décorateur est largement utilisé par les producteurs ; certaines classes sont donc destinées à ajouter des nouveaux comportements et de nouvelles fonctionnalités aux writers de base. Voici quelques-unes des classes de producteurs que vous serez amenés à manipuler le plus souvent :

  • java.io.BufferedWriter - décore un producteur en lui s’associant un tampon mémoire  ;
  • java.io.CharArrayWriter - permet de manipuler un tableau de caractères (char[]) dans un producteur ;
  • java.io.OutputStreamWriter - empaquète un flux de sortie (OutputStream) dans un producteur ;
  • java.io.FileReader - empaquète un flux de sortie vers un fichier (FileOutputStream) dans un producteur :
  • java.io.PipedWriter - permet de connecter une liseuse PipedReader sur un producteur ;
  • java.io.PrintWriter - décore un producteur de manière à pouvoir utiliser des méthodes de formatage de chaines de caractères ;
  • java.io.StringWriter - permet de manipuler un constructeur de chaines de caractères (StringBuffer) comme un producteur de manière à produire des chaines de caractères (String).

Mis à jour le 17 août 2015 bouye

Il arrive que l’accès de manière séquentielle aux octets d'un fichier via les flux ne soit pas suffisant pour des opérations de lecture/écriture. Ceci est souvent le cas lorsqu'on gère des fichiers binaires dans lesquels un accès direct (ou accès aléatoire, random access) est souvent requis : il faut sauter à un décalage spécifique dans le fichier ou revenir en arrière plus tard, remplacer le contenu d'un groupe spécifique d'octets, etc. Même si certains types de flux peuvent supporter la notion de marque et de restauration de contexte, ce n'est pas toujours le cas et ils se révèlent en général peu adaptés à cet usage.

Dans l'API Java classique, la classe java.io.RandomAccessFile permet de bénéficier d'un accès direct tant en lecture qu'en écriture sur un fichier. Cette classe permet de déplacer un curseur à un décalage spécifique dans le fichier en invoquant la méthode seek(), ce qui permet d'effectuer l’opération de lecture ou d’écriture à cet emplacement précis. La plupart des opérations sur cette classe sont susceptibles de générer des exceptions de type IOException en cas d'erreur.

De par sa nature, cette classe est attachée à une ressource native (fichier) qui doit être libérée lorsque vous avez fini d'utiliser l'instance. Vous devez donc invoquer sa méthode close() lorsque vous avez fini de la manipuler. Cette classe implémente l'interface AutoClosable, il est ainsi possible de l'utiliser dans une construction try-with-resources qui fermera automatiquement l'instance en fin de bloc.

Avertissent : vous devez garder à l'esprit que Java est Big-Endian. Lorsque vous lisez ou écrivez une structure d'octets complexe (short, int, long, etc.) dans un tel fichier, cette dernière sera lue ou écrite au format Big-Endian !

De plus, vous devez également vous rappeler que les caractères en Java (char) sont codés sur 16 bits (2 octets) et non pas sur 8 bits (1 octet) comme dans d'autres langages.

Pour ouvrir un fichier en accès direct en lecture :

Code Java : Sélectionner tout
1
2
3
4
try (RandomAccessFile file = new RandomAccessFile("fichier.bin", "r")) { 
    // Lecture du fichier. 
    [...] 
}

Et pour un accès direct en écriture :

Code Java : Sélectionner tout
1
2
3
4
try (RandomAccessFile file = new RandomAccessFile("fichier.bin", "rw")) { 
    // Écriture du fichier. 
    [...] 
}

Mis à jour le 13 août 2015 bouye

Dans l'API NIO, un canal ou channel est un concept introduit dans le JDK 1.4 et mis en œuvre via l'interface java.nio.channels.Channel ainsi que ses interfaces filles et ses nombreuses implémentations. Un canal représente une connexion vers une entité telle qu'un fichier, un périphérique, une socket réseau ou encore une partie d'un logiciel, etc. capable d'effectuer des opérations I/O telles que la lecture et l’écriture. Un canal a deux états : ouvert ou fermé ; il est ouvert lors de sa création et peut être alors fermé. Une fois qu'il est fermé, le canal le reste.

Les canaux sont destinés à permettre d'effectuer des opérations en accès direct (ou accès aléatoire ou random access) de manière non bloquante (asynchrone). Ils permettent, entre autres de manipuler des fichiers de très grande taille. Par exemple, la classe java.nio.channels.FileChannel permet d'obtenir un canal permettant de manipuler un fichier. Cette classe hérite de plusieurs types de canaux qui lui permettent de lire et d’écrire des octets, mais aussi de déplacer son curseur de lecture/écriture dans le fichier et de mapper un tampon mémoire contenant une partie du fichier, ce que ne permet pas de faire aisément un flux classique.

De par sa nature, cette classe est attachée à une ressource native (fichier) qui doit être libérée lorsque vous avez fini d'utiliser l'instance. Vous devez donc invoquer sa méthode close() lorsque vous avez fini de la manipuler. Cette classe implémente l'interface AutoClosable, il est ainsi possible de l'utiliser dans une construction try-with-resources qui fermera automatiquement l'instance en fin de bloc.

Mis à jour le 13 août 2015 bouye

Voici quelques-unes des classes de canaux que vous serez amenés à manipuler le plus souvent :

  • java.nio.channels.AsynchronousFileChannel - un canal associé à un fichier supportant les opérations asynchrones ;
  • java.nio.channels.AsynchronousServerSocketChannel - un canal associé à une socket serveur supportant les opérations asynchrones ;
  • java.nio.channels.AsynchronousSocketChannel- un canal associé à une socket supportant les opérations asynchrones ;
  • java.nio.channels.DatagramChannel - un canal associé à une socket supportant les datagrammes ;
  • java.nio.channels.FileChannel - un canal associé à un fichier ;
  • java.nio.channels.ServerSocketChannel - un canal associé à une socket serveur ;
  • java.nio.channels.SocketChannel - un canal associé à une socket.

Mis à jour le 17 août 2015 bouye

Dans l'API NIO, un tampon ou buffer est un concept introduit dans le JDK 1.4 et mis en œuvre via la classe java.nio.Buffer ainsi que ses classes filles. Ces objets sont utilisés pour lire et écrire des données sur les canaux. Un tampon représente un espace linéaire et fini (d'une capacité limitée) d'un certain type de données (byte, char, short, etc.).

Un tampon contient également un curseur qui est la position à laquelle peut s'effectuer l’opération de lecture/écriture ; cette position ne peut pas être négative ou être positionnée au-delà de la limite du tampon. La limite est la position maximale des données au-delà de laquelle on ne peut plus lire ni écrire. Il est de plus possible de poser une marque qui permet un retour rapide du curseur à cette position. De manière générale on a : 0 ≤ marque ≤ position ≤ limite ≤ capacité.

Les tampons disposent de plusieurs méthodes dont il faut bien comprendre l'usage :

  • clear() - cette opération réinitialise complètement le tampon, sa position et sa capacité. Elle doit être invoquée avant de lire le contenu d'un canal ;
  • flip() - cette opération modifie la limite à la positon actuelle avant de réinitialiser la position. Elle doit être invoquée avant de pouvoir écrire un tampon dans un canal ;
  • rewind() - cette opération réinitialise la position et permet d’accéder à nouveau aux données contenues. Elle peut être utilisée pour, par exemple, copier le contenu d'un tampon dans un tableau après que le tampon a été écrit dans un canal.


Mis à jour le 13 août 2015 bouye

Voici quelques-unes des classes de tampons que vous serez amenés à manipuler le plus souvent :

  • java.nio.ByteBuffer - un tampon de bytes (octets) :
    • java.nio.MappedByteBuffer - un tampon d'octets dans une région de la mémoire en accès direct créé à partir d'un canal vers un fichier (FileChannel) ;
  • java.nio.CharBuffer - un tampon spécialisé dans la manipulation de char obtenu à partir d'un ByteBuffer ;
  • java.nio.DoubleBuffer - un tampon spécialisé dans la manipulation de double obtenu à partir d'un ByteBuffer ;
  • java.nio.FloatBuffer - un tampon spécialisé dans la manipulation de float obtenu à partir d'un ByteBuffer ;
  • java.nio.IntBuffer - un tampon spécialisé dans la manipulation d'int obtenu à partir d'un ByteBuffer ;
  • java.nio.LongBuffer - un tampon spécialisé dans la manipulation de long obtenu à partir d'un ByteBuffer ;
  • java.nio.ShortBuffer - un tampon spécialisé dans la manipulation de short obtenu à partir d'un ByteBuffer.

Mis à jour le 17 août 2015 bouye

La machine virtuelle Java (et plus précisément le Garbage Collector ou ramasse-miettes) s'occupe de libérer proprement la mémoire lorsque les objets ne sont plus utilisés. Toutefois, il existe un certain nombre de ressources qui doivent être libérées explicitement, par exemple les fichiers, les sockets ou les connexions JDBC, car elles utilisent des ressources système qui ne peuvent pas être gérées par le Garbage Collector. Ces ressources doivent être « libérées » explicitement grâce à une méthode spécifique (généralement nommée close()).

Or, on ne peut pas se contenter d'appeler cette méthode à la fin du traitement, car il y a un certain nombre de cas où cette méthode ne serait pas appelée ; par exemple en cas d'exception ou de retour de la méthode. Il est également fortement déconseillé d'appeler cette méthode aux divers points de sortie du code (fin du traitement, dans les catch, avant les return, etc.), car cela complexifie le code et son traitement, et augmente ainsi les chances de se tromper (en oubliant un cas particulier par exemple).

JDK antérieurs au JDK 7
La solution la plus propre à mettre en œuvre est d'utiliser un bloc try/finally qui respecte la structure suivante :

Code Java : Sélectionner tout
1
2
3
4
5
6
// 1 - Création de la ressource. 
try { 
    // 2 - Utilisation de la ressource. 
} finally { 
    // 3 - Libération de la ressource. 
}

Ainsi, lorsque la ressource est correctement créée, on l'utilise exclusivement à l'intérieur du try, et on la libère dans le bloc finally quoi qu'il arrive. En effet, si on rentre dans le bloc try, le code du bloc finally sera exécuté dans tous les cas lorsqu'on sort de celui-ci, même si une exception est générée ou que l'on quitte la méthode avec return... Cette organisation en trois étapes permet donc de garantir la libération propre des ressources dans tous les cas.

Par exemple le code permettant de lire un fichier texte pourrait ressembler à ceci :

Code Java : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public static String readFile(File file) throws IOException, FileNotFoundException { 
    // 1 - Création de la ressource. 
    FileReader reader = new FileReader(file); 
    try { 
        // 2 - Utilisation de la ressource. 
        StringBuffer buffer = new StringBuffer(); 
        char[] cbuf = new char[2048]; 
        int len; 
        while ((len = reader.read(cbuf)) > 0) { 
            buffer.append(cbuf, 0, len); 
        } 
        return buffer.toString(); 
    } finally { 
        // 3 - Libération de la ressource. 
        reader.close(); 
    } 
}

Cela permet de faire remonter simplement les exceptions à la méthode appelante tout en fermant correctement la ressource (ici, une instance de FileReader).

De la même manière, si l'on souhaite gérer les exceptions dans la méthode, il est préférable d'utiliser un bloc try/catch en plus du bloc try/finally et non pas un bloc try/catch/finally qui nécessiterait un nouveau try/catch dans le bloc finally (et donc un double traitement des exceptions).

Par exemple :

Code Java : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public static String readFile(File file) { 
    try { 
        // 1 - Création de la ressource. 
        FileReader reader = new FileReader(file); 
        try { 
            // 2 - Utilisation de la ressource. 
            StringBuffer buffer = new StringBuffer(); 
            char[] cbuf = new char[2048]; 
            int len; 
            while ( (len = reader.read(cbuf)) > 0 ) { 
                buffer.append(cbuf, 0, len); 
            } 
            return buffer.toString(); 
        } finally { 
            // 3 - Libération de la ressource. 
            reader.close(); 
        } 
    } catch (IOException e) { 
        e.printStackTrace(); 
        return null; 
    } 
}

Enfin, si l'on utilise plusieurs ressources à la fois, il ne faut pas hésiter à encapsuler plusieurs try/finally (un par ressource). Par exemple dans ce code qui permet de sauvegarder une URL dans un fichier :

Code java : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public static void writeToFile(URL url, File file) throws IOException, FileNotFoundException { 
    // 1 - Création de la ressource (Fichier). 
    FileOutputStream fos = new FileOutputStream(file); 
    try { 
        // 2 - Utilisation de la ressource (Fichier). 
        // 1 - Création de la ressource (URL). 
        InputStream is = url.openStream(); 
        try { 
            // 2 - Utilisation de la ressource (URL). 
            byte[] buf = new byte[2048]; 
            int len; 
            while ( (len = is.read(buf)) > 0) { 
                fos.write(buf, 0 , len); 
            } 
        } finally { 
            // 3 - Libération de la ressource (URL). 
            is.close(); 
        } 
    } finally { 
        // 3 - Libération de la ressource (Fichier). 
        fos.close(); 
    } 
}

Si cela peut avoir peu d'importance dans une application de bureau, c'est nettement plus critique dans une application serveur, car on peut vite atteindre les limites autorisées par le système, et se retrouver avec une application complètement bloquée !

À noter enfin que le Garbage Collector « limite » quand même ce phénomène, car la méthode close() est généralement appelée implicitement lors de la destruction de l'objet (plus précisément via la méthode finalize()) si la ressource n'a pas été fermée explicitement. Toutefois, étant donné que l'on ne peut pas maîtriser le passage du Garbage Collector avec exactitude, il est préférable de fermer les ressources explicitement avec un bloc try/finally.

JDK7
À partir du JDK7, il est possible de largement simplifier ces bouts de code en utilisant une construction de type try-with-resource qui se chargera d'invoquer les méthodes close() de toutes les ressources de type AutoClosable qui y ont été déclarées.

Pour la lecture de fichier simple :

Code Java : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public static String readFile(File file) throws IOException, FileNotFoundException { 
    // 1 - Création de la ressource 
    try (FileReader reader = new FileReader(file)) { 
        // 2 - Utilisation de la ressource 
        StringBuffer buffer = new StringBuffer(); 
        char[] cbuf = new char[2048]; 
        int len; 
        while ((len = reader.read(cbuf)) > 0) { 
            buffer.append(cbuf, 0, len); 
        } 
        return buffer.toString(); 
        // 3 - Libération implicite de la ressource. 
    } 
}

Pour la lecture de fichier avec interception d'exception :

Code Java : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public static String readFile(File file) { 
    // 1 - Création de la ressource  
    try (FileReader reader = new FileReader(file)) { 
        // 2 - Utilisation de la ressource  
        StringBuffer buffer = new StringBuffer(); 
        char[] cbuf = new char[2048]; 
        int len; 
        while ((len = reader.read(cbuf)) > 0) { 
            buffer.append(cbuf, 0, len); 
        } 
        return buffer.toString(); 
        // 3 - Libération implicite de la ressource. 
    } catch (IOException e) { 
        e.printStackTrace(); 
        return null; 
    } 
}

Pour la gestion de plusieurs ressources :

Code Java : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
public static void writeToFile(URL url, File file) throws IOException, FileNotFoundException { 
    // 1 - Création des ressources (Fichier et URL).      
    try (FileOutputStream fos = new FileOutputStream(file); 
            InputStream is = url.openStream()) { 
        // 2 - Utilisation des ressources (Fichier et URL)  
        byte[] buf = new byte[2048]; 
        int len; 
        while ((len = is.read(buf)) > 0) { 
            fos.write(buf, 0, len); 
        } 
        // 3 - Libération implicite des ressources (Fichier et URL). 
    } 
}

Ici, lors de la sortie du bloc try, les méthodes des deux flux sont implicitement invoquées dans l'ordre inverse de la déclaration des flux (la méthode close() de is sera invoquée avant la méthode close() de fos).

Mis à jour le 13 août 2015 adiGuba bouye

Les sorties standards sont accessibles au programmeur grâce aux flux statiques out et err de la classe java.lang.System. Le flux in permet d’accéder à la sortie standard tandis que le flux err permet d’accéder à l'erreur standard.

Ces deux flux sont des instances de la classe java.io.PrintStream ; cette classe permet d'utiliser les variantes des méthodes print() et println() pour effectuer des sorties formatées. Depuis le JDK 5, il est également possible d'utiliser les variantes des méthodes printf() et format().

Code Java : Sélectionner tout
1
2
3
4
// Imprime sur la sortie standard. 
System.out.println("Salut le monde !"); 
// Imprime sur l'erreur standard. 
System.err.println("Erreur");

Avertissement : si vous invoquez la méthode close() sur ces flux, vous ne pourrez plus les ouvrir après cet appel et tout ce que vous imprimerez sur les sorties sera alors perdu.

Mis à jour le 13 août 2015 bouye

L'entrée standard est accessible au programmeur grâce au flux statique in de la classe java.lang.System. Si vous exécutez votre application dans une console, elle contiendra tous les caractères entrés au clavier.

JDK antérieur au JDK 5
La manipulation directe du flux n'étant pas très aisée, une petite conversion en java.io.BufferedReader s'impose.

Code Java : Sélectionner tout
1
2
3
4
5
6
7
BufferedReader entree = new BufferedReader(new InputStreamReader(System.in)); 
try { 
    // Lecture d'une ligne :  
    String ligne = entree.readLine(); 
} catch( IOException e ) { 
        e.printStackTrace(); 
}

La lecture d'une ligne est une méthode dite « bloquante » : c'est-à-dire que le processus appelant est en pause tant que l'utilisateur n'a pas appuyé sur la touche Entrée du clavier.

Note : Ici, on n'invoque pas la méthode close() des liseuses pour ne pas fermer le flux d’entrée de la console.

JDK 5
À partir du JDK 5, vous pouvez aussi utiliser un java.util.Scanner pour parser la sortie standard.

Par exemple :
Code Java : Sélectionner tout
1
2
3
4
Scanner scanner = new Scanner(System.in); 
// Traitement. 
[...] 
scanner.close();

Le Scanner a l'avantage de posséder un ensemble de méthodes permettant de lire directement les types primitifs. Vous pouvez aussi l'utiliser pour faire des recherches dans les flux scannés avec des expressions régulières.

JDK 6
À partir du JDK 6, il est possible de lire sur l'entrée standard via la classe java.io.Console.

Par exemple :

Code Java : Sélectionner tout
1
2
Console console = System.console(); 
String ligne = console.readLine();

La classe Console propose également la méthode readPassword() qui n'affiche pas les caractères sur la console.

Mis à jour le 13 août 2015 bouye Clement Cunin

Si pour une raison quelconque, vous avez besoin de récupérer dans des fichiers tout ce qui arrive sur la sortie standard, il suffit d'employer les méthodes setOut() et setErr() de la classe System :

Code Java : Sélectionner tout
1
2
System.setOut(new PrintStream(new FileOutputStream("out.log"))); 
System.setErr(new PrintStream(new FileOutputStream("err.log")));

Mis à jour le 11 novembre 2006 bentechno

Oui, cela est possible. Ceci peut être utile par exemple pour afficher correctement les caractères accentués.

Voici un exemple permettant d'écrire correctement les caractères accentués sur la console Windows (DOS, CMD) :

Code Java : Sélectionner tout
1
2
3
4
5
PrintStream ps = new PrintStream(System.out, true, "IBM850"); 
// On commence par changer l'encodage en IBM850 (connu aussi sous l'alias Cp850). 
System.setOut(ps); 
// Ensuite, l'utilisation de la sortie standard reste la même 
System.out.println("àâäÂÄéèêëîïÎÏÊËôöÔÖûüùÛÜÿç");

Mis à jour le 9 septembre 2004 Ioan

Pour charger une ressource présente sur le CLASSPATH (depuis un répertoire ou une archive JAR), il faut utiliser les méthodes getResource() et getResourceAsStream() de la classe Class. Le chemin à passer en argument est celui commençant dans le répertoire du CLASSPATH ou à la racine d'un fichier JAR.

Attention : si le chemin ne commence pas par / alors le package courant est ajouté au début du chemin.

Par exemple :

Code Java : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
package com.developpez;  
  
public class Test {  
  
    public Test() {  
        try (InputStream is1 = getClass().getResourceAsStream("fichier.txt") ;   
                InputStream is2 = getClass().getResourceAsStream("/fichier.txt")) { 
            [...] 
        } 
    }  
}

Dans le code de l'exemple, is1 sera un flux ouvert sur un fichier com/developpez/fichier.txt présent dans un des répertoires du CLASSPATH ou dans la même arborescence à partir de la racine d'un fichier JAR du CLASSPATH. is2 sera, quant à lui, un flux ouvert sur un fichier fichier.txt présent directement dans un répertoire du CLASSPATH ou à la racine d'un fichier JAR.

Mis à jour le 19 juillet 2004 bulbo

On peut spécifier l'encodage utilisé pour lire un flux. Voici un exemple qui lit un fichier en UTF-8 et écrit celui-ci en ISO-8859-1 :

Code Java : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
public static void toISO(String source, String destination){ 
    try (BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(source),"UTF-8")) ; // Flux de lecture en UTF-8. 
            PrintWriter pw = new PrintWriter(new FileOutputStream(destination))) {    // Flux d'écriture en ISO (valeur par défaut). 
        String ligne; 
        while ((ligne = br.readLine()) != null) { 
            pw.println(ligne); 
        } 
    } catch (Exception e) { 
        e.printStackTrace(); 
    }    
}

Mis à jour le 9 septembre 2004 Ioan

La classe java.nio.Charset nous permet de facilement accéder à ces informations.

Voici un exemple listant l'ensemble des charsets disponibles :

Code Java : Sélectionner tout
1
2
3
4
5
6
7
8
9
SortedMap<String,Charset> charsets = Charset.availableCharsets(); 
for (String nom : charsets.keySet()) { 
    System.out.println("Charset "+nom); 
    Charset charset = charsets.get(nom); 
    for (String alias : charset.aliases()) { 
        System.out.print(" "+alias+","); 
    } 
    System.out.println(); 
}

Mis à jour le 9 septembre 2004 Ioan

JDK antérieurs au JDK 7
Il est possible d'obtenir une instance de FileChannel en invoquant la méthode getChannel() des classes de l'API Java classique : java.io.FileInputStream, java.io.FileOutputStream et java.io.RandomAccessFile.

Code Java : Sélectionner tout
1
2
3
4
5
6
try (FileChannel channel = new RandomAccessFile("fichier.bin", "r").getChannel()) { 
    // Faire quelque chose sur le fichier. 
    [...] 
} catch (IOException ex) { 
    System.out.println("Erreur --" + ex.toString()); 
}

Le canal ainsi obtenu est un singleton et toute modification effectuée sur le canal (écriture, déplacement de curseur, etc.) s'appliquera également sur le flux ou le fichier parent et inversement.

JDK 7
À partir du JDK 7, il est possible d'invoquer la méthode statique open() de la classe java.nio.channels.FileChannel pour obtenir un tel canal :

Code Java : Sélectionner tout
1
2
3
4
5
6
try (FileChannel channel = FileChannel.open(Paths.get("fichier.bin"), StandardOpenOption.READ)) { 
   // Faire quelque chose sur le fichier. 
   [...] 
} catch (IOException ex) { 
    System.out.println("Erreur --" + ex.toString()); 
}

Il est également possible d'invoquer la méthode statique newByteChannel() de la classe utilitaire java.nio.file.Files :

Code Java : Sélectionner tout
1
2
3
4
5
6
try (SeekableByteChannel channel = Files.newByteChannel(Paths.get("fichier.bin"), StandardOpenOption.READ)) { 
   // Faire quelque chose sur le fichier. 
   [...] 
} catch (IOException ex) { 
    System.out.println("Erreur --" + ex.toString()); 
}

Mis à jour le 13 août 2015 bouye

Vous pouvez utiliser une ou plusieurs des valeurs définies dans l'enum java.nio.file.StandardOpenOption pour modifier le mode d'ouverture de votre canal :

  • StandardOpenOption.APPEND - l’écriture se fait en fin de fichier ;
  • StandardOpenOption.CREATE - si le fichier n'existe pas, le créer ; ne rien faire si le fichier existe ;
  • StandardOpenOption.CREATE_NEW - si le fichier n'existe pas, le créer ; générer une exception si le fichier existe ;
  • StandardOpenOption.DELETE_ON_CLOSE - tente de supprimer le fichier à la fermeture du canal ; sinon tenter de le supprimer lorsque la JVM se termine (sans erreur) ;
  • StandardOpenOption.DSYNC - force l’écriture immédiate de toutes modifications du fichier de manière synchrone ;
  • StandardOpenOption.READ - ouverture en lecture ;
  • StandardOpenOption.SPARSE - tente de créer un fichier compact si le système de fichier supporte cette option ;
  • StandardOpenOption.SYNC - force l’écriture immédiate de toutes modifications du fichier ou de ses métadonnées de manière synchrone ;
  • StandardOpenOption.TRUNCATE_EXISTING - tronque tout fichier existant en mettant sa taille à zéro ;
  • StandardOpenOption.WRITE - ouverture en écriture.


Note : si vous obtenez votre canal à partir des classes de l'API Java classique, le canal obtenu héritera ses capacités de celles de son parent :
  • FileInputStream - le canal peut être utilisé uniquement en lecture : équivalent de StandardOpenOption.READ ;
  • FileOutputStream - le canal peut être utilisé uniquement en écriture. Si le paramètre append vaut :
    • true : équivalent de StandardOpenOption.CREATE + StandardOpenOption.APPEND + StandardOpenOption.WRITE,
    • false : équivalent de StandardOpenOption.CREATE + StandardOpenOption.TRUNCATE_EXISTING + StandardOpenOption.WRITE ;
  • RandomAccessfile - le mode du canal dépend du mode d'ouverture du fichier :
    • "r" : équivalent de StandardOpenOption.READ,
    • "rw" : équivalent de StandardOpenOption.CREATE + StandardOpenOption.WRITE + StandardOpenOption.READ.

Mis à jour le 14 août 2015 bouye

Il est possible de créer un tampon en mémoire en invoquant la méthode map() de la classe java.nio.channels.FileChannel.

Par exemple pour un petit fichier, nous pouvons faire :

Code Java : Sélectionner tout
1
2
3
4
5
6
try (FileChannel channel = FileChannel.open(Paths.get("fichier.bin"), StandardOpenOption.READ)) {  
    MappedByteBuffer buffer = channel.map(FileChannel.MapMode.READ_ONLY, 0, channel.size());  
    [...]  
} catch (IOException ex) {  
    System.out.println("Erreur --" + ex.toString());  
}

Ici, nous avons mappé le contenu du fichier en mémoire dans son intégralité.

Pour des fichiers de plus grande taille, il faudra s’attacher travailler sur le fichier « par morceau » et à déplacer le tampon comme si on déplaçait une vue ou une fenêtre sur le contenu du fichier.

Mis à jour le 13 août 2015 bouye

Java est Big-Endian et ses flux ainsi que la classe RandomAccessFile lisent les données en Big-Endian également. Ceci peut poser problème si vous cherchez à lire ou à écrire des fichiers dont le format est originaire du monde du PC (par exemple des anciens formats binaires pour Microsoft Office). En effet :

  • Big-Endian - les octets de poids fort sont à gauche : architecture IBM, CRAY, Sun, etc. ;
  • Little-Endian - les octets de poids faible sont à gauche : architecture Intel.


Prenons par exemple le nombre entier (32bit) 3 :

Code Console : Sélectionner tout
1
2
3 sur une machine gros-boutiste  ↔ 00000000 00000000 00000000 00000011 ↔ 50331648 sur une machine petit-boutiste.  
3 sur une machine petit-boutiste ↔ 00000011 00000000 00000000 00000000 ↔ 50331648 sur une machine gros-boutiste.

API Java classique
Il n'existe pas de méthode standardisée dans l'API classique pour lire et écrire des données binaires au format Little-Endian. En l'absence de méthode standard, vous allez devoir vous créer des routines qui vous permettent d'inverser les octets lors de la lecture ou de l’écriture de structures d'octets complexes (short, int, long, etc.). Par exemple, la méthode suivante inverse les octets d'un int (entier 32bit) :

Code Java : Sélectionner tout
1
2
3
4
5
6
7
8
public static int invertIntBytes(int value) { 
    int a = (value >> 24) & 0xFF; 
    int b = (value >> 16) & 0xFF; 
    int c = (value >> 8) & 0xFF; 
    int d = value & 0xFF; 
    int result = (d << 24) | (c << 16) | (b << 8) | a; 
    return result; 
}

Vous devrez ensuite invoquer cette méthode au moment approprié lors de la lecture ou de l’écriture de votre fichier.

Pour la lecture :

Code Java : Sélectionner tout
1
2
3
4
5
try (DataInputStream input = new DataInputStream(new FileInputStream("fichier.bin"))) { 
    int value = invertIntBytes(input.readInt()); // Pour lire 3, il faudra lire 00000011 00000000 00000000 00000000. 
} catch (IOException ex) { 
    System.out.println("Erreur --" + ex.toString()); 
}

Pour l’écriture :

Code Java : Sélectionner tout
1
2
3
4
5
try (DataOutputStream output = new DataOutputStream(new FileOutputStream("fichier.bin"))) { 
    output.writeInt(invertIntBytes(3)); // Le contenu généré sera  00000011 00000000 00000000 00000000.  
} catch (IOException ex) { 
    System.out.println("Erreur --" + ex.toString()); 
}

NIO
Vous pouvez invoquer la méthode order() d'un ByteBuffer en lui passant en paramètre une instance de la classe java.nio.ByteOrder. Actuellement, cette classe définit deux valeurs :

  • ByteOrder.BIG_ENDIAN - les octets de poids fort sont à gauche : architecture IBM, CRAY, Sun, etc. Il s'agit de la valeur par défaut puisque Java est Big-Endian ;
  • ByteOrder.LITTLE_ENDIAN - les octets de poids faible sont à gauche : architecture Intel.


Pour la lecture :

Code Java : Sélectionner tout
1
2
3
4
5
6
7
8
try (FileChannel channel = FileChannel.open(Paths.get("fichier.bin"), StandardOpenOption.READ)) { 
    MappedByteBuffer buffer = channel.map(FileChannel.MapMode.READ_ONLY, 0, channel.size()); 
    buffer.order(ByteOrder.LITTLE_ENDIAN); 
    final int value = buffer.getInt(); // Pour lire 3, il faudra lire 00000011 00000000 00000000 00000000. 
    System.out.println(value); 
} catch (IOException ex) { 
    System.out.println("Erreur --" + ex.toString()); 
}

Pour l’écriture :

Code Java : Sélectionner tout
1
2
3
4
5
6
7
8
9
try (FileChannel channel = FileChannel.open(Paths.get("fichier.bin"), StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING, StandardOpenOption.WRITE)) { 
    ByteBuffer buffer = ByteBuffer.allocate(4); 
    buffer.order(ByteOrder.LITTLE_ENDIAN); 
    buffer.putInt(3); // Le contenu généré sera  00000011 00000000 00000000 00000000. 
    buffer.flip(); 
    channel.write(buffer); 
} catch (IOException ex) { 
    System.out.println("Erreur --" + ex.toString()); 
}

Invoquer la méthode order() (sans paramètre) retourne la configuration du tampon.

Mis à jour le 13 août 2015 bouye

Le traitement d'un fichier ligne par ligne est assez simple, mais il faut quand même connaître les différentes manières de s'y prendre :

API Java classique
BufferedReader
Nous allons utiliser un simple BufferedReader pour lire le fichier et ensuite utiliser la méthode readLine() pour lire une ligne de notre fichier. Voilà donc ce que pourrait donner notre code :

Code Java : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
try (BufferedReader buff = new BufferedReader(new FileReader("fichier.txt"))) { 
    String line; 
    // Lecture du fichier ligne par ligne. 
    // Cette boucle se termine quand la méthode retourne la valeur null.  
    while ((line = buff.readLine()) != null) { 
        System.out.println(line); 
        // Faites ici votre traitement. 
        [...] 
    } 
} catch (IOException ioe) { 
    System.out.println("Erreur --" + ioe.toString()); 
}


LineNumberReader
La classe LineNumberReader permet également de connaître les numéros des lignes lues dans le fichier.

Code Java : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
try (LineNumberReader buff = new LineNumberReader(new FileReader("fichier.txt"))) { 
    String line; 
    // Lecture du fichier ligne par ligne.  
    // Cette boucle se termine quand la méthode retourne la valeur null.  
    try { 
        while ((line = buff.readLine()) != null) { 
            System.out.println(line); 
            // Faites ici votre traitement. 
            [...] 
        } 
    } catch (IOException ioe) { 
        System.out.println("Erreur ligne #" + buff.getLineNumber()); 
        throw ioe; 
    } 
} catch (IOException ioe) { 
    System.out.println("Erreur --" + ioe.toString()); 
}

Scanner
À partir du JDK 5, on peut également utiliser la classe java.util.Scanner pour lire un fichier ligne par ligne :

Code Java : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
try (Scanner scanner = new Scanner(new File("fichier.txt"))) { 
    // On boucle sur chaque champ détecté. 
    while (scanner.hasNextLine()) { 
        String line = scanner.nextLine(); 
        System.out.println(line); 
        // Faites ici votre traitement. 
        [...] 
    } 
} catch (FileNotFoundException ex) { 
    System.out.println("Erreur --" + ex.toString()); 
}

NIO2
JDK 7
À partir du JDK 7, il est possible d'invoquer la méthode statique readAllLines() de la classe utilitaire java.nio.file.Files pour lire toutes les lignes d'un fichier texte :

Code Java : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
try { 
    List<String> lines = Files.readAllLines(Paths.get("fichier.txt")); 
    for (String line : lines) { 
        System.out.println(line); 
        // Faites ici votre traitement. 
        [...] 
    } 
} catch (IOException ex) { 
    System.out.println("Erreur --" + ex.toString()); 
}

Cette méthode est bloquante tant que le contenu du fichier n'a pas été intégralement chargé en mémoire.

JDK 8
À partir du JDK 8, il est possible d'utiliser les flux de données (data stream ou stream) en invoquant la méthode statique lines() de la classe utilitaire java.nio.file.Files pour lire toutes les lignes d'un fichier texte :

Code Java : Sélectionner tout
1
2
3
4
5
6
7
8
9
try (Stream<String> lines = Files.lines(Paths.get("fichier.txt"))) { 
    lines.forEach(line -> { 
        System.out.println(line); 
        // Faites ici votre traitement. 
        [...] 
    }); 
} catch (IOException ex) { 
    System.out.println("Erreur --" + ex.toString()); 
}

Le flux retourné par l'invocation de cette méthode est peuplé de manière lazy (paresseuse), c'est-à-dire que le fichier n'est pas intégralement lu à l'avance et les lignes de texte sont chargées en mémoire au au fur et à mesure de l’accès au contenu du flux.

Mis à jour le 13 août 2015 bentechno bouye sironimo

À partir du JDK 5, pour lire les éléments d'un fichier en utilisant un délimiteur, il suffit d'avoir recours à la classe java.util.Scanner.

Par exemple pour lire un fichier dont les champs sont séparés par des tabulations, on pourra écrire :

Code Java : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
try (Reader reader = new FileReader("fichier.txt")) { 
    Scanner scanner = new Scanner(reader); 
    // L'expression régulière qui délimite les champs. 
    scanner.useDelimiter(Pattern.compile("[\t\n]")); 
    // On boucle sur chaque champ détecté. 
    int champ; 
    while (scanner.hasNext()) { 
        // Si le champ n'est pas un entier, une exception de type InputMismatchException sera générée. 
        champ = scanner.nextInt(); 
        // Utilisation du champ... 
        [...] 
    }         
}

Mis à jour le 13 août 2015 bobuse

API Java classique
FileOutputStream
Pour écrire à la fin d'un fichier binaire, il faut utiliser la classe java.io.FileOutputStream ; cette classe possède des constructeurs acceptant parmi leurs arguments un booléen nommé append. Si cet argument est positionné à la valeur true, les données écrites dans ce fichier seront mises à la fin de celui-ci :

Code Java : Sélectionner tout
1
2
3
4
String texte = "texte à insérer à la fin du fichier"; 
try (FileOutputStream output = new FileOutputStream("fichier.bin", true)) { 
    output.write(texte.getBytes("utf-8")); 
}

Writer
Pour écrire à la fin d'un fichier texte, il faut utiliser la classe java.io.FileWriter ; cette classe possède des constructeurs acceptant parmi leurs arguments un booléen nommé append. Si cet argument est positionné à la valeur true, les données écrites dans ce fichier seront mises à la fin de celui-ci :

Code Java : Sélectionner tout
1
2
3
4
String texte = "texte à insérer à la fin du fichier"; 
try (FileWriter writer = new FileWriter("fichier.txt", true)) { 
    writer.write(texte); 
}

RandomAccessFile
Pour écrire à la fin de votre fichier binaire en utilisant la classe java.io.RandomAccessFile, vous devez déplacer le curseur à la fin du fichier en invoquant la méthode seek() avant de tenter d'y écrire :

Code Java : Sélectionner tout
1
2
3
4
5
String texte = "texte à insérer à la fin du fichier"; 
try (RandomAccessFile file = new RandomAccessFile("fichier.bin", "rw")) {  
    file.seek(file.length()); 
    file.writeUTF(texte); 
}

NIO2
Vous pouvez invoquer la méthode statique write() de la classe utilitaire java.nio.file.Files en spécifiant les options StandardOpenOption.CREATE (pour créer le fichier s'il n'existe pas déjà) et StandardOpenOption.APPEND (pour écrire à la fin du fichier s'il existe déjà) :

Code Java : Sélectionner tout
1
2
String texte = "texte à insérer à la fin du fichier";  
Files.write(Paths.get("fichier.txt"), texte.getBytes("utf-8"), StandardOpenOption.CREATE, StandardOpenOption.APPEND);

Mis à jour le 13 août 2015 bouye bulbo

De nombreux formats de fichiers texte peuvent être utilisés avec Java. Malheureusement, tous ne sont pas utilisables grâce à l'API standard. Voici quelques formats et les API qui peuvent les utiliser :

Format API Remarques
HTML API Standard Cf. HTMLEditorKit, JEditorPane et JTextPane
RTF API Standard Cf. RTFEditorKit, JEditorPane et JTextPane
XML API Standard (SAX, DOM) Il existe de nombreuses bibliothèques facilitant le travail avec ce type de documents
PDF iText, FOP Ces deux bibliothèques sont utilisées seulement pour la génération
Excel POI, JExcelAPI
Word POI

Mis à jour le 10 octobre 2015 duj Ioan

Proposer une nouvelle réponse sur la FAQ

Ce n'est pas l'endroit pour poser des questions, allez plutôt sur le forum de la rubrique pour ça


Réponse à la question

Liens sous la question
précédent sommaire suivant
 

Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright © 2024 Developpez Developpez LLC. Tous droits réservés Developpez LLC. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents et images sans l'autorisation expresse de Developpez LLC. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.