1. Flux de données
Il est rare qu'un programme existe comme une île en soi. Les programmes interagissent généralement d'une manière ou d'une autre avec le "monde extérieur". Cela peut se produire en lisant des données à partir du clavier, en envoyant des messages, en téléchargeant des pages depuis Internet ou, à l'inverse, en téléchargeant des fichiers sur un serveur distant.
Nous pouvons résumer tous ces comportements en un mot : échange de données entre le programme et le monde extérieur. Attendez, ce n'est pas juste un mot.
Bien sûr, l'échange de données lui-même peut être divisé en deux parties : la réception de données et l'envoi de données. Par exemple, vous lisez des données à partir du clavier à l'aide d'un Scanner
objet — celui-ci reçoit des données. Et vous affichez des données à l'écran à l'aide d'une System.out.println()
commande - c'est l'envoi de données.
En programmation, le terme "flux" est utilisé pour décrire l'échange de données. D'où vient ce terme ?
Dans la vraie vie, vous pouvez avoir un courant d'eau ou un courant de conscience. En programmation, nous avons des flux de données .
Les flux sont un outil polyvalent. Ils permettent au programme de recevoir des données de n'importe où (flux d'entrée) et d'envoyer des données n'importe où (flux de sortie). Ainsi, il existe deux types :
- Un flux d'entrée sert à recevoir des données
- Un flux de sortie sert à envoyer des données
Pour rendre les flux "tangibles", les créateurs de Java ont écrit deux classes : InputStream
et OutputStream
.
La InputStream
classe a une read()
méthode qui vous permet de lire des données à partir de celle-ci. Et la OutputStream
classe a une write()
méthode qui vous permet d'y écrire des données. Ils ont également d'autres méthodes, mais nous en reparlerons plus tard.
Flux d'octets
De quel type de données parle-t-on ? Quel format prend-il ? En d'autres termes, quels types de données ces classes prennent-elles en charge ?
Ce sont des classes génériques, elles prennent donc en charge le type de données le plus courant — le byte
. Un OutputStream
peut écrire des octets (et des tableaux d'octets), et un InputStream
objet peut lire des octets (ou des tableaux d'octets). C'est tout - ils ne prennent en charge aucun autre type de données.
Par conséquent, ces flux sont également appelés flux d'octets .
Une caractéristique des flux est que leurs données ne peuvent être lues (ou écrites) que séquentiellement. Vous ne pouvez pas lire des données au milieu d'un flux sans lire toutes les données qui le précèdent.
C'est ainsi que la lecture des données du clavier fonctionne dans la Scanner
classe : vous lisez les données du clavier de manière séquentielle, ligne par ligne. Nous lisons une ligne, puis la ligne suivante, puis la ligne suivante, et ainsi de suite. À juste titre, la méthode de lecture des lignes s'appelle nextLine()
.
L'écriture de données dans un OutputStream
se produit également de manière séquentielle. Un bon exemple de ceci est la sortie de la console. Vous sortez une ligne, suivie d'une autre et d'une autre. Il s'agit d'une sortie séquentielle. Vous ne pouvez pas afficher la première ligne, puis la dixième, puis la seconde. Toutes les données sont écrites dans un flux de sortie uniquement de manière séquentielle.
Flux de caractères
Vous avez récemment appris que les chaînes sont le deuxième type de données le plus populaire, et elles le sont effectivement. De nombreuses informations sont transmises sous forme de caractères et de chaînes entières. Un ordinateur excelle dans l'envoi et la réception de tout sous forme d'octets, mais les humains ne sont pas si parfaits.
Tenant compte de ce fait, les programmeurs Java ont écrit deux autres classes : Reader
et Writer
. La Reader
classe est analogue à la InputStream
classe, mais sa read()
méthode lit non pas des octets, mais des caractères ( char
). La Writer
classe correspond à la OutputStream
classe. Et tout comme la Reader
classe, cela fonctionne avec des caractères ( char
), pas des octets.
Si nous comparons ces quatre classes, nous obtenons l'image suivante :
Octets (octet) | Caractères (char) | |
---|---|---|
Lecture des données |
|
|
Données d'écriture |
|
|
Application pratique
Les classes InputStream
, et elles-mêmes ne sont utilisées directement par personne, car elles ne sont associées à aucun objet concret à partir duquel des données peuvent être lues (ou dans lesquelles des données peuvent être écrites) OutputStream
. Mais ces quatre classes ont beaucoup de classes descendantes qui peuvent faire beaucoup.Reader
Writer
2. InputStream
classe
La InputStream
classe est intéressante car c'est la classe mère de centaines de classes descendantes. Il n'a pas de données propres, mais il a des méthodes dont héritent toutes ses classes dérivées.
En général, il est rare que des objets de flux stockent des données en interne. Un flux est un outil de lecture/écriture de données, mais pas de stockage. Cela dit, il y a des exceptions.
Méthodes de la InputStream
classe et de toutes ses classes descendantes :
Méthodes | Description |
---|---|
|
Lit un octet du flux |
|
Lit un tableau d'octets à partir du flux |
|
Lit tous les octets du flux |
|
Ignore n les octets dans le flux (les lit et les supprime) |
|
Vérifie le nombre d'octets restants dans le flux |
|
Ferme le flux |
Passons brièvement en revue ces méthodes :
read()
méthode
La read()
méthode lit un octet du flux et le renvoie. Vous pourriez être confus par le int
type de retour. Ce type a été choisi car int
il s'agit du type entier standard. Les trois premiers octets de int
seront zéro.
read(byte[] buffer)
méthode
C'est la deuxième variante de la read()
méthode. Il vous permet de lire un tableau d'octets à partir d'un InputStream
tout à la fois. Le tableau qui stockera les octets doit être passé en argument. La méthode renvoie un nombre — le nombre d'octets réellement lus.
Supposons que vous disposiez d'un tampon de 10 kilo-octets et que vous lisiez des données à partir d'un fichier à l'aide de la FileInputStream
classe. Si le fichier ne contient que 2 kilo-octets, toutes les données seront chargées dans le tableau de tampons et la méthode renverra le nombre 2048 (2 kilo-octets).
readAllBytes()
méthode
Une très bonne méthode. Il lit simplement toutes les données du InputStream
jusqu'à ce qu'il soit épuisé et les renvoie sous la forme d'un tableau à un seul octet. C'est très pratique pour lire de petits fichiers. Les fichiers volumineux peuvent ne pas tenir physiquement dans la mémoire et la méthode lèvera une exception.
skip(long n)
méthode
Cette méthode vous permet d'ignorer les n premiers octets de l' InputStream
objet. Étant donné que les données sont lues de manière strictement séquentielle, cette méthode lit simplement les n premiers octets du flux et les supprime.
Renvoie le nombre d'octets qui ont été réellement ignorés (au cas où le flux s'est terminé avant que n
les octets aient été ignorés).
int available()
méthode
La méthode renvoie le nombre d'octets qui restent dans le flux
void close()
méthode
Le close()
procédé ferme le flux de données et libère les ressources externes qui lui sont associées. Une fois qu'un flux est fermé, plus aucune donnée ne peut être lue à partir de celui-ci.
Écrivons un exemple de programme qui copie un très gros fichier. Nous ne pouvons pas utiliser la readAllBytes()
méthode pour lire le fichier entier en mémoire. Exemple:
Code | Note |
---|---|
|
InputStream pour lire depuis le fichier OutputStream pour écrire dans le fichier Tampon dans lequel nous allons lire les données Tant qu'il y a des données dans le flux Lire les données dans le tampon Écrire les données du tampon dans le second flux |
Dans cet exemple, nous avons utilisé deux classes : FileInputStream
est un descendant de InputStream
pour lire des données dans un fichier et FileOutputStream
est un descendant de OutputStream
pour écrire des données dans un fichier. Nous parlerons de la deuxième classe un peu plus tard.
Un autre point intéressant ici est la real
variable. Lorsque le dernier bloc de données est lu à partir d'un fichier, il peut facilement contenir moins de 64 Ko de données. En conséquence, nous devons sortir non pas l'intégralité du tampon, mais seulement une partie de celui-ci - les premiers real
octets. C'est exactement ce qui se passe dans la write()
méthode.
3. Reader
classe
La Reader
classe est un analogue complet de la InputStream
classe. La seule différence est que cela fonctionne avec des caractères ( char
), pas avec des octets. Tout comme la InputStream
classe, la Reader
classe n'est utilisée nulle part seule : c'est la classe parente de centaines de classes descendantes et elle définit des méthodes communes pour toutes.
Méthodes de la Reader
classe (et de toutes ses classes descendantes) :
Méthodes | Description |
---|---|
|
En lit un char à partir du flux |
|
Lit un char tableau à partir du flux |
|
Ignore n chars le flux (le lit et le supprime) |
|
Vérifie s'il reste encore quelque chose dans le flux |
|
Ferme le flux |
Les méthodes sont très similaires à celles de la InputStream
classe, bien qu'il existe de légères différences.
int read()
méthode
Cette méthode en lit un char
dans le flux et le renvoie. Le char
type s'élargit à un int
, mais les deux premiers octets du résultat sont toujours zéro.
int read(char[] buffer)
méthode
C'est la deuxième variante de la read()
méthode. Il vous permet de lire un tableau de caractères à partir d'un Reader
tout à la fois. Le tableau qui stockera les caractères doit être passé en argument. La méthode renvoie un nombre — le nombre de caractères réellement lus.
skip(long n)
méthode
Cette méthode vous permet d'ignorer les n premiers caractères de l' Reader
objet. Cela fonctionne exactement de la même manière que la méthode analogue de la InputStream
classe. Renvoie le nombre de caractères réellement ignorés.
boolean ready()
méthode
Renvoie true
s'il y a des octets non lus dans le flux.
void close()
méthode
Le close()
procédé ferme le flux de données et libère les ressources externes qui lui sont associées. Une fois qu'un flux est fermé, plus aucune donnée ne peut être lue à partir de celui-ci.
A titre de comparaison, écrivons un programme qui copie un fichier texte :
Code | Note |
---|---|
|
Reader pour lire à partir d'un fichier Writer pour écrire dans un fichier Tampon dans lequel nous allons lire les données Tant qu'il y a des données dans le flux Lire les données dans un tampon Écrire les données du tampon dans le second flux |
GO TO FULL VERSION