Le concept de « stream » provient du concept de pipe sous UNIX. Sous UNIX, un canal est un flux d'octets ininterrompu utilisé pour mettre en œuvre la communication entre des programmes ou des processus, ou pour lire et écrire des périphériques, des fichiers externes, etc. Il protège les détails du traitement des données dans le périphérique d'E/S réel. Un flux doit avoir une source et une destination, qui peuvent être certaines zones de la mémoire de l'ordinateur, des fichiers sur disque ou même une URL sur Internet. La direction du flux est importante. Selon la direction du flux, le flux peut être divisé en deux catégories : le flux d’entrée et le flux de sortie. En fait, les entrées/sorties sont destinées à la mémoire. En fait, la source et la destination du flux peuvent être simplement considérées comme des producteurs et des consommateurs d'octets. Pour le flux d'entrée, vous n'avez pas besoin de vous soucier de sa source, tant que vous lisez simplement les données du flux, et. pour le flux d'entrée Le flux de sortie peut également ignorer sa destination et simplement écrire des données dans le flux.
a. Stream : un ensemble de séquences de données ordonnées.
b Flux d'octets : la plus petite unité de données du flux de données est l'octet.
c. Flux de caractères : la plus petite unité de données du flux de données est un caractère.
1. Les classes du package java.io correspondent à deux types de flux
Un type de flux lit ou écrit directement à partir d'un emplacement spécifié (tel qu'un fichier disque ou une zone mémoire). Ce type de flux est appelé flux de nœud, et d'autres flux sont appelés flux de filtre (flux de packaging).
Filtrage des flux : certains flux peuvent recevoir des octets provenant de fichiers et d'ailleurs, et d'autres flux peuvent combiner des octets en types de données plus utiles. Un constructeur qui transmet un flux existant à un autre flux et combine les deux flux. Le flux combiné est appelé flux filtré. Le flux d'entrée du filtre utilise souvent d'autres flux d'entrée comme source d'entrée. Après filtrage ou traitement, il est fourni à l'utilisateur sous la forme d'un nouveau flux d'entrée. Le flux de sortie du filtre est similaire. Nous utilisons rarement une seule classe pour créer un objet de flux, mais fournissons plutôt la fonctionnalité souhaitée en superposant plusieurs objets (c'est-à-dire le modèle de conception du décorateur).
Les flux d'entrée et de sortie couramment utilisés de Java sont en fait hérités de quatre classes abstraites, à savoir :
Basé sur la classe InputStream à un octet, OutputStream (E/S orientées octet)
Classes de lecture et d'écriture basées sur des unités de code Unicode à deux octets (E/S orientées caractères)
Une fois le flux d'entrée ouvert, le programme peut lire les données en série à partir du flux d'entrée. Le processus de lecture/écriture des données du flux d'entrée est généralement le suivant : ouvrir un canal de flux --> lire/écrire des informations --> fermer le canal de flux.
Dans la plateforme Java, il existe deux manières d'obtenir le type de codage de caractères de la plateforme locale :
(a) System.getProperty("file.encoding");
(b) Jeu de caractères cs=Charset.defaultCharset();
Tous les flux d'entrée et de sortie peuvent être divisés en flux d'octets (entrée, sortie) et en flux de caractères (entrée, sortie). Ceux qui traitent les octets sont principalement des séries (OutputStream/InputStream), et ceux qui traitent les caractères sont principalement (Reader/Write). ) série
2. Flux d'entrée orientés octets (série InputStream), ces classes peuvent être connectées aux objets FileInputStream pour fournir des interfaces utiles :
ByteArrayInputStream : utiliser un tampon en mémoire comme InputStream
StringBufferInputStream (obsolète dans java1.1) : utilisez un objet String comme InputStream et l'implémentation sous-jacente utilise StringBuffer
FileInputStream : utiliser un fichier comme InputStream pour implémenter l'opération de lecture de fichier (nom de fichier, fichier, objet FileDescriptor)
PipedInputStream : implémente le concept de pipe, principalement utilisé dans les threads (comme source de données dans plusieurs processus)
SequenceInputStream : combinez plusieurs InputStreams en un seul InputStream
Les flux de sortie orientés octets (série OutputStream) peuvent être connectés aux objets FilterOutputStream pour fournir des interfaces utiles :
ByteArrayOutputStream : crée un tampon en mémoire, stocke les informations dans un tampon en mémoire et initialise la taille du tampon (facultatif)
FileOutputStream : stocker les informations dans un fichier (nom du fichier, fichier, FileDescriptor)
PipedOutputStream : implémente le concept de pipe, principalement utilisé dans les threads (précise la destination des données pour les multi-threads)
3. La série (Lecteur/Écrivain) correspondante :
Reader : Correspondant à InputStream, adaptateur InputStreamReader
Writer : correspond à OutputStream et l'adaptateur est OutputStreamWriter
FileReader : correspond à FileOutputStream
FileWriter : correspond à FileOurputStream
StringReader : aucune classe correspondante
StringWriter : correspond à ByteArrayInputStream
CharArrayReader : correspond à ByteArrayOutputStream
CharArrayWriter : correspond à ByteArrayOutputStream
PipedReader : correspond à PipedInputStream
PipedWriter : correspond à PipedOutputStream
4. Conversion entre deux flux sans restriction ( en utilisant la classe adaptateur)
InputStreamReader et OutputStreamReader : convertissez un flux orienté octets en un flux orienté caractères.
InputStreamReader est un pont entre un flux d'octets et un flux de caractères : il lit les octets à l'aide d'un jeu de caractères spécifié et les décode en caractères. Le jeu de caractères qu'il utilise peut être spécifié par son nom ou donné explicitement, ou il peut accepter le jeu de caractères par défaut de la plateforme.
OutputStreamWriter est un pont entre le flux de caractères et le flux d'octets : les caractères à écrire dans le flux peuvent être codés en octets à l'aide du jeu de caractères spécifié. Le jeu de caractères qu'il utilise peut être spécifié par son nom ou donné explicitement, sinon le jeu de caractères par défaut de la plateforme sera accepté.
5. Lisez les données de InputStream via FilterInputStream :
DataInputStream : lit les données de type de base (int, char, long, etc.) à partir du flux.
BufferedInputStream : utilisez un tampon pour éviter d'avoir à effectuer une opération de lecture réelle à chaque fois
LineNumberInputStream : enregistrera le nombre de lignes dans le flux d'entrée, puis appellera getLineNumber() et setLineNumber(int)
PushbackInputStream : rarement utilisé, généralement utilisé pour le développement de compilateurs
Écrivez dans OutputStream via FilterOutputStream :
DataIOutputStream : les données de type de base (int, char, long, etc.) peuvent être sorties dans le flux selon la méthode de transplantation.
BufferedOutputStream : utilisez un tampon pour éviter l'écriture réelle à chaque fois que vous envoyez des données
PrintStream : produit une sortie formatée, où DataOutputStream gère le stockage des données et PrintStream gère l'affichage.
6. Changer le comportement du flux
Bien que BufferedOutputStream soit une sous-classe de FilterOutputStream, BufferedWriter n'est pas une sous-classe de FilterWriter (FilterWriter est une classe abstraite et n'a aucune sous-classe)
Il n'existe pas de classe correspondante pour DataInputStream. Utilisez DataInputStream sauf si vous utilisez BufferedReader à la place lorsque vous souhaitez utiliser readLine()
BufferedReader : correspond à BufferedInputStream
LineNumberReader : correspond à LineNumberInputStream
PushBackReader : correspond à PushbackInputStream
BufferedWrite : correspond à BufferedOutStream
PrintWrite : correspond à PrintStream
7. Classe autonome : RandomAccessFile
Cette classe convient aux fichiers composés d'enregistrements de taille connue. En plus d'implémenter les interfaces DataInput et DataOutput (DataInputStream et DataOutputStream implémentent également ces deux interfaces), RandomAccessFile est une classe complètement indépendante et d'autres types d'E/S. différents comportements, peuvent avancer et reculer dans un fichier et sont directement dérivés d'Object.
Les opérations de lecture et d'écriture sur les fichiers peuvent être effectuées via l'objet RandomAccessFile.
Lors de la génération d'un objet, vous pouvez spécifier la nature du fichier à ouvrir : r, lecture seule ; w, écriture seule ; rw peut lire et écrire ;
Vous pouvez accéder directement à l'emplacement spécifié dans le fichier
La plupart (mais pas toutes) des fonctionnalités de RandomAccessFile ont été remplacées par des fichiers de mappage de stockage Nio.