Flux, fichiers et E/S Java

Les flux, les fichiers et les E/S (entrées/sorties) en Java constituent l'infrastructure pour gérer la lecture et l'écriture de données. Ils permettent aux programmes d'interagir avec des données externes (telles que des fichiers, des réseaux, l'entrée système, etc.).

Le paquet java.io est un paquet central de la bibliothèque standard Java, fournissant des classes pour l'entrée et la sortie système. Il contient des outils pour gérer les flux de données (flux d'octets et flux de caractères), la lecture et l'écriture de fichiers, la sérialisation et le formatage des données.

java.io est le paquet fondamental pour gérer les opérations sur les fichiers, les opérations sur les flux et les opérations d'E/S de bas niveau.

Les flux du paquet java.io prennent en charge de nombreux formats, tels que les types primitifs, les objets, les jeux de caractères localisés, etc.

Un flux peut être compris comme une séquence de données. Un flux d'entrée représente la lecture de données depuis une source, et un flux de sortie représente l'écriture de données vers une destination.


Lecture de l'entrée console

L'entrée console en Java est gérée par System.in.

Pour obtenir un flux de caractères lié à la console, vous pouvez envelopper System.in dans un objet BufferedReader afin de créer un flux de caractères.

Voici la syntaxe de base pour créer un BufferedReader :

BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

Après la création de l'objet BufferedReader, nous pouvons utiliser la méthode read() pour lire un caractère depuis la console, ou la méthode readLine() pour lire une chaîne.


Lecture de plusieurs caractères depuis l'entrée de la console

Pour lire un caractère à partir d'un objet BufferedReader, utilisez la méthode read(). Sa syntaxe est la suivante :

int read( ) throws IOException

Chaque fois que la méthode read() est appelée, elle lit un caractère dans le flux d'entrée et renvoie le caractère sous forme de valeur entière. Elle renvoie -1 lorsque le flux se termine. Cette méthode lève une IOException.

Le programme suivant montre comment utiliser la méthode read() pour lire en continu des caractères depuis la console jusqu'à ce que l'utilisateur saisisseq。

Code du fichier BRRead.java :

//Lecture de caractères depuis la console à l'aide de BufferedReader import java.io.*; public class BRRead { public static void main(String[] args) throws IOException { char c; //Créer un BufferedReader en utilisant System.in BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); System.out.println("Saisissez des caractères, appuyez sur 'q' pour quitter."); //Lecture de caractères do { c = (char) br.read(); System.out.println(c); } while (c != 'q'); } }

Le résultat de compilation et d'exécution de l'exemple ci-dessus est le suivant :

输入字符, 按下 'q' 键退出。
example
r
u
n
o
o
b


q
q

Lecture de chaînes depuis l'entrée console

Pour lire une chaîne depuis l'entrée standard, vous devez utiliser la méthode readLine() de BufferedReader.

Son format général est :

String readLine( ) throws IOException

Le programme suivant lit et affiche des lignes de caractères jusqu'à ce que vous saisissiez le mot "end".

Code du fichier BRReadLines.java :

//Lecture de caractères depuis la console à l'aide de BufferedReader import java.io.*; public class BRReadLines { public static void main(String[] args) throws IOException { //Créer un BufferedReader en utilisant System.in BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); String str; System.out.println("Saisissez des lignes de texte."); System.out.println("Entrez 'end' pour quitter."); do { str = br.readLine(); System.out.println(str); } while (!str.equals("end")); } }

Le résultat de compilation et d'exécution de l'exemple ci-dessus est le suivant :

Enter lines of text.
Enter 'end' to quit.
This is line one
This is line one
This is line two
This is line two
end
end

Dans les versions après JDK 5, nous pouvons également utiliser la classeScannerde Java pour obtenir une entrée console.


Sortie console

Comme introduit précédemment, la sortie console est réalisée par print() et println(). Ces méthodes sont toutes définies par la classe PrintStream, et System.out est une référence à un objet de cette classe.

PrintStream hérite de la classe OutputStream et implémente la méthode write(). Ainsi, write() peut également être utilisée pour écrire dans la console.

La forme la plus simple de write() définie par PrintStream est la suivante :

void write(int byteval)

Cette méthode écrit les huit bits de poids faible de byteval dans le flux.

Exemple

L'exemple suivant utilise write() pour afficher le caractère "A" suivi d'un saut de ligne à l'écran :

Code du fichier WriteDemo.java :

import java.io.*; //Démontre System.out.write(). public class WriteDemo { public static void main(String[] args) { int b; b = 'A'; System.out.write(b); System.out.write('\n'); } }

L'exécution de l'exemple ci-dessus affiche le caractère "A" dans la fenêtre de sortie.

A

Remarque :La méthode write() n'est pas fréquemment utilisée car les méthodes print() et println() sont plus pratiques à utiliser.


Lecture et écriture de fichiers

Comme mentionné précédemment, un flux est défini comme une séquence de données. Les flux d'entrée sont utilisés pour lire des données à partir d'une source, et les flux de sortie sont utilisés pour écrire des données vers une destination.

Le diagramme suivant est un diagramme de hiérarchie de classes décrivant les flux d'entrée et les flux de sortie.

Flux d'octets (gestion des données binaires)

Les flux d'octets sont utilisés pour traiter des données binaires, telles que des fichiers, des images, des vidéos, etc.

Nom de classeTypeDescription
InputStreamClasse abstraite (flux d'entrée)La superclasse de tous les flux d'entrée d'octets, gérant les opérations d'entrée d'octets.
OutputStreamClasse abstraite (flux de sortie)La superclasse de tous les flux de sortie d'octets, gérant les opérations de sortie d'octets.
FileInputStreamFlux d'entréeLit des données d'octets à partir d'un fichier.
FileOutputStreamFlux de sortieÉcrit des données d'octets dans un fichier.
BufferedInputStreamFlux d'entréeFournit une mise en mémoire tampon pour les flux d'entrée d'octets afin d'améliorer l'efficacité de lecture.
BufferedOutputStreamFlux de sortieFournit une mise en mémoire tampon pour les flux de sortie d'octets afin d'améliorer l'efficacité d'écriture.
ByteArrayInputStreamFlux d'entréeUtilise un tableau d'octets en mémoire comme source d'entrée.
ByteArrayOutputStreamFlux de sortieÉcrit des données dans un tableau d'octets en mémoire.
DataInputStreamFlux d'entréePermet de lire des types de données primitifs Java depuis un flux d'entrée (tel queint、float、boolean)。
DataOutputStreamFlux de sortiePermet d'écrire des types de données primitifs Java vers un flux de sortie.
ObjectInputStreamFlux d'entréeLit des objets sérialisés depuis un flux d'entrée.
ObjectOutputStreamFlux de sortieSérialise des objets et les écrit dans un flux de sortie.
PipedInputStreamFlux d'entréeUtilisé pour lire des données d'octets dans un tube, généralement avecPipedOutputStreamUtilisés ensemble.
PipedOutputStreamFlux de sortieUtilisé pour écrire des données d'octets dans un tube, généralement avecPipedInputStreamUtilisés ensemble.
FilterInputStreamFlux d'entréeUne classe wrapper pour les flux d'entrée d'octets, utilisée pour effectuer un filtrage sur d'autres flux d'entrée.
FilterOutputStreamFlux de sortieUne classe wrapper pour les flux de sortie d'octets, utilisée pour effectuer un filtrage sur d'autres flux de sortie.
SequenceInputStreamFlux d'entréeCombine plusieurs flux d'entrée en un seul flux d'entrée pour le traitement.

Flux de caractères (traitement des données textuelles)

Les flux de caractères sont utilisés pour gérer des données textuelles, comme la lecture et l'écriture de chaînes ou l'écriture de chaînes ou

Nom de classeTypeDescription
ReaderClasse abstraite (flux d'entrée)La superclasse de tous les flux d'entrée de caractères, gérant les opérations d'entrée de caractères.
WriterClasse abstraite (flux de sortie)La superclasse de tous les flux de sortie de caractères, gérant les opérations de sortie de caractères.
FileReaderFlux d'entréeLit des données de caractères depuis un fichier.
FileWriterFlux de sortieÉcrit des données de caractères dans un fichier.
BufferedReaderFlux d'entréeFournit une mise en mémoire tampon pour les flux d’entrée de caractères, prend en charge la lecture ligne par ligne et améliore l’efficacité de lecture.
BufferedWriterFlux de sortieFournit une mise en mémoire tampon pour les flux de sortie de caractères, prend en charge l’écriture ligne par ligne et améliore l’efficacité d’écriture.
CharArrayReaderFlux d'entréeUtilise un tableau de caractères comme source d’entrée.
CharArrayWriterFlux de sortieÉcrit des données dans un tableau de caractères.
StringReaderFlux d'entréeUtilise une chaîne de caractères comme source d’entrée.
StringWriterFlux de sortieÉcrit des données dans un tampon de chaîne.
PrintWriterFlux de sortieFlux de sortie de caractères pratique, prend en charge le vidage automatique et la sortie formatée.
PipedReaderFlux d'entréeUtilisé pour lire des données de caractères dans un pipe, généralement avecPipedWriterutilisé ensemble.
PipedWriterFlux de sortieUtilisé pour écrire des données de caractères dans un pipe, généralement avecPipedReaderutilisé ensemble.
LineNumberReaderFlux d'entréeFlux d'entrée de caractères mis en tampon avec numéros de ligne, permettant de suivre le numéro de ligne en cours de lecture.
PushbackReaderFlux d'entréePermet de repousser des caractères dans le flux après lecture, afin qu'ils puissent être lus à nouveau.

Classes utilitaires (autres classes importantes)

Les classes utilitaires fournissent un support pour les fichiers, les répertoires et l'accès aléatoire aux fichiers.

Nom de classeTypeDescription
FileOpérations sur les fichiers et les répertoiresUtilisé pour représenter un fichier ou un répertoire, et fournit des opérations sur les fichiers telles que la création, la suppression, le renommage, etc.
RandomAccessFileFichier à accès aléatoirePrend en charge l'accès aléatoire aux fichiers, permettant de lire et d'écrire des données à n'importe quelle position dans le fichier.
ConsoleEntrée/sortie de la consoleFournit une prise en charge des entrées et sorties pour la console système.

Les deux flux importants qui seront abordés ensuite sontFileInputStreametFileOutputStream。


FileInputStream

Ce flux est utilisé pour lire des données depuis un fichier. Son objet peut être créé en utilisant le mot-clé new.

Il existe plusieurs constructeurs qui peuvent être utilisés pour créer des objets.

Vous pouvez utiliser un nom de fichier de type chaîne pour créer un objet de flux d'entrée afin de lire un fichier :

InputStream f = new FileInputStream("C:/java/hello");

Vous pouvez également utiliser un objet fichier pour créer un objet de flux d'entrée afin de lire un fichier. Nous devons d'abord utiliser la méthode File() pour créer un objet fichier :

File f = new File("C:/java/hello"); InputStream in = new FileInputStream(f);

Une fois l'objet InputStream créé, vous pouvez utiliser les méthodes suivantes pour lire le flux ou effectuer d'autres opérations de flux.

MéthodeDescriptionExemple de code
int read()Lit un octet de données, la valeur de retour étant un entier compris entre 0 et 255. Renvoie -1 si la fin du flux est atteinte.int data = inputStream.read();
int read(byte[] b)Lit des octets depuis le flux d'entrée et les stocke dans le tableau d'octetsbet renvoie le nombre réel d'octets lus. Renvoie -1 si la fin du flux est atteinte.byte[] buffer = new byte[1024]; int bytesRead = inputStream.read(buffer);
int read(byte[] b, int off, int len)Lit jusqu'àlenoctets depuis le flux d'entrée et les stocke dans le tableau d'octetsbdeoffà partir de la position de décalage, en renvoyant le nombre réel d'octets lus. Renvoie -1 si la fin du flux est atteinte.byte[] buffer = new byte[1024]; int bytesRead = inputStream.read(buffer, 0, buffer.length);
long skip(long n)Ignore et supprimenoctets dans le flux d'entrée, en renvoyant le nombre réel d'octets ignorés.long skippedBytes = inputStream.skip(100);
int available()Renvoie le nombre d'octets qui peuvent être lus (sans blocage).int availableBytes = inputStream.available();
void close()Ferme le flux d'entrée et libère toutes les ressources associées à ce flux.inputStream.close();
void mark(int readlimit)Définit une marque à la position actuelle dans le flux,readlimitest la limite supérieure du nombre d'octets qui peuvent être lus.inputStream.mark(1024);
void reset()Repositionne le flux à la position de la dernière marque. S'il n'y a pas de marque ou si la marque est invalide, lèveIOException。inputStream.reset();
boolean markSupported()Vérifie si le flux d'entrée actuel prend en chargemark()etreset()l'opération.boolean isMarkSupported = inputStream.markSupported();

En plus de InputStream, il existe d'autres flux d'entrée. Pour plus de détails, reportez-vous au lien ci-dessous :


FileOutputStream

Cette classe est utilisée pour créer un fichier et écrire des données dans le fichier.

Si le fichier cible n'existe pas avant que le flux n'ouvre le fichier pour la sortie, le flux créera le fichier.

Il existe deux constructeurs qui peuvent être utilisés pour créer un objet FileOutputStream.

Utilisez un nom de fichier de type chaîne pour créer un objet de flux de sortie :

OutputStream f = new FileOutputStream("C:/java/hello")

Vous pouvez également utiliser un objet fichier pour créer un flux de sortie afin d'écrire dans un fichier. Nous devons d'abord utiliser la méthode File() pour créer un objet fichier :

File f = new File("C:/java/hello"); OutputStream fOut = new FileOutputStream(f);

Après avoir créé l'objet OutputStream, vous pouvez utiliser les méthodes suivantes pour écrire dans le flux ou effectuer d'autres opérations sur le flux.

MéthodeDescriptionExemple de code
void write(int b)Écrit l'octet spécifié dans le flux de sortie ; les 8 bits de poids faible debseront écrits dans le flux.outputStream.write(255);
void write(byte[] b)Écrit tous les octets du tableau d'octetsbvers le flux de sortie.byte[] data = "Hello".getBytes(); outputStream.write(data);
void write(byte[] b, int off, int len)Écrit des octets à partir du tableau d'octetsben commençant au décalageoffen commençant àlenoctets vers le flux de sortie.byte[] data = "Hello".getBytes(); outputStream.write(data, 0, data.length);
void flush()Vide le flux de sortie et force toutes les données mises en mémoire tampon à être écrites, en garantissant que les données sont immédiatement écrites vers la sortie cible.outputStream.flush();
void close()Ferme le flux de sortie et libère toutes les ressources associées à ce flux. Après fermeture, aucune autre écriture ne peut être effectuée.outputStream.close();

En plus de OutputStream, il existe d'autres flux de sortie. Pour plus de détails, reportez-vous au lien ci-dessous :

Exemple

L'exemple suivant illustre l'utilisation de InputStream et OutputStream :

code du fichier fileStreamTest.java :

import java.io.*; public class fileStreamTest { public static void main(String[] args) { try { byte bWrite[] = { 11, 21, 3, 40, 5 }; OutputStream os = new FileOutputStream("test.txt"); for (int x = 0; x < bWrite.length; x++) { os.write(bWrite[x]); // écrit les octets } os.close(); InputStream is = new FileInputStream("test.txt"); int size = is.available(); for (int i = 0; i < size; i++) { System.out.print((char) is.read() + " "); } is.close(); } catch (IOException e) { System.out.print("Exception"); } } }

Le programme ci-dessus crée d'abord le fichier test.txt, écrit les nombres donnés dans le fichier sous forme binaire, et en même temps les affiche dans la console.

Comme le code ci-dessus utilise l'écriture binaire, des caractères illisibles peuvent apparaître. Vous pouvez utiliser l'exemple de code suivant pour résoudre le problème des caractères illisibles :

Code du fichier fileStreamTest2.java :

//Nom du fichier : fileStreamTest2.java import java.io.*; public class fileStreamTest2 { public static void main(String[] args) throws IOException { File f = new File("a.txt"); FileOutputStream fop = new FileOutputStream(f); //Construire un objet FileOutputStream. Si le fichier n'existe pas, il sera créé automatiquement. OutputStreamWriter writer = new OutputStreamWriter(fop, "UTF-8"); //Construire un objet OutputStreamWriter. Le paramètre peut spécifier l'encodage ; par défaut, il s'agit de l'encodage par défaut du système d'exploitation, qui est gbk sous Windows. writer.append("Chinese input"); //Écrire dans le tampon writer.append("\r\n"); //Newline writer.append("English"); //Vider le tampon et écrire dans le fichier. S'il n'y a plus de contenu à écrire ci-dessous, appeler directement close écrira aussi. writer.close(); //Fermer le flux d'écriture ; en même temps, le contenu du tampon sera écrit dans le fichier, donc ce qui précède est commenté. fop.close(); //Fermer le flux de sortie et libérer les ressources système. FileInputStream fip = new FileInputStream(f); //Construire un objet FileInputStream. InputStreamReader reader = new InputStreamReader(fip, "UTF-8"); //Construire un objet InputStreamReader ; l'encodage est le même que lors de l'écriture. StringBuffer sb = new StringBuffer(); while (reader.ready()) { sb.append((char) reader.read()); //Convertir en char et l'ajouter à l'objet StringBuffer. } System.out.println(sb.toString()); reader.close(); //Ferme le flux de lecture. fip.close(); //Ferme le flux d'entrée et libère les ressources système. } }

Fichiers et E/S

Il y a aussi quelques classes liées aux fichiers et aux E/S que nous devons connaître :


Répertoires en Java

Création de répertoires :

Il existe deux méthodes dans la classe File qui peuvent être utilisées pour créer des dossiers :

  • mkdir( )La méthode crée un dossier. Elle renvoie true en cas de succès et false en cas d'échec. L'échec indique que le chemin spécifié par l'objet File existe déjà, ou que le dossier ne peut pas être créé parce que le chemin complet n'existe pas encore.
  • mkdirs()La méthode crée un dossier et tous ses dossiers parents.

L'exemple suivant crée le dossier "/tmp/user/java/bin" :

Code du fichier CreateDir.java :

import java.io.File; public class CreateDir { public static void main(String[] args) { String dirname = "/tmp/user/java/bin"; File d = new File(dirname); //Création du répertoire en cours d.mkdirs(); } }

Compilez et exécutez le code ci-dessus pour créer le répertoire "/tmp/user/java/bin".

Remarque :Java distingue automatiquement les séparateurs de chemin de fichiers selon la convention sous UNIX et Windows. Si vous utilisez le séparateur (/) dans une version Windows de Java, le chemin peut toujours être résolu correctement.


Lecture des répertoires

Un répertoire est en fait un objet File qui contient d'autres fichiers et dossiers.

Si vous créez un objet File et qu'il s'agit d'un répertoire, alors l'appel de la méthode isDirectory() renverra true.

Vous pouvez extraire la liste des fichiers et dossiers qu'il contient en appelant la méthode list() sur cet objet.

L'exemple ci-dessous montre comment utiliser la méthode list() pour vérifier le contenu d'un dossier :

Code du fichier DirList.java :

import java.io.File; public class DirList { public static void main(String args[]) { String dirname = "/tmp"; File f1 = new File(dirname); if (f1.isDirectory()) { System.out.println("Directory" + dirname); String s[] = f1.list(); for (int i = 0; i < s.length; i++) { File f = new File(dirname + "/" + s[i]); if (f.isDirectory()) { System.out.println(s[i] + "est un répertoire"); } else { System.out.println(s[i] + "est un fichier"); } } } else { System.out.println(dirname + "n'est pas un répertoire"); } } }

Le résultat de la compilation et de l'exécution de l'exemple ci-dessus est le suivant :

目录 /tmp
bin 是一个目录
lib 是一个目录
demo 是一个目录
test.txt 是一个文件
README 是一个文件
index.html 是一个文件
include 是一个目录

Suppression de répertoires ou de fichiers

Pour supprimer un fichier, vous pouvez utiliser la méthodejava.io.File.delete().

Le code suivant supprimera le répertoire/tmp/java/. Notez que lors de la suppression d'un répertoire, vous devez vous assurer qu'il n'y a pas d'autres fichiers dans ce répertoire pour le supprimer correctement ; sinon, la suppression échouera.

Structure du répertoire de test :

/tmp/java/
|-- 1.log
|-- test

Code du fichier DeleteFileDemo.java :

import java.io.File; public class DeleteFileDemo { public static void main(String[] args) { //Modifiez ceci pour votre propre répertoire de test File folder = new File("/tmp/java/"); deleteFolder(folder); } //Supprimer des fichiers et des répertoires public static void deleteFolder(File folder) { File[] files = folder.listFiles(); if (files != null) { for (File f : files) { if (f.isDirectory()) { deleteFolder(f); } else { f.delete(); } } } folder.effacement(); } }
Autres extensions