Salut! Les leçons et les tâches du niveau 3 vous ont appris à afficher des éléments sur la console et, dans l'autre sens, à lire les données du clavier.
Vous avez même appris à utiliser la construction complexe suivante pour y parvenir :
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
Mais il y a une question à laquelle nous n'avons pas encore répondu.
Comment diable cela fonctionne-t-il ?
En réalité, les programmes sont rarement entièrement indépendants. Ils communiquent avec d'autres programmes, systèmes, Internet, etc. Par "communiquer", nous entendons principalement "échanger des données". Autrement dit, ils reçoivent des données externes et envoient également des données de programme internes quelque part. Les exemples de programmes échangeant des données abondent dans la vie de tous les jours. Par exemple, de nombreux sites Web vous permettent de vous connecter à l'aide de votre compte Facebook ou Twitter au lieu de vous inscrire. Dans cette situation, deux programmes (par exemple Twitter et le site Web auquel vous vous connectez) échangent les données nécessaires. Le résultat final est que vous êtes connecté avec succès. Le mot "stream"est utilisé pour décrire le processus d'échange de données. D'où vient ce nom ? D'après votre expérience, un « ruisseau » peut être davantage associé aux rivières qu'à la programmation. Ce n'est pas un hasard :) Un flux est, par essence, une donnée en mouvement. En d'autres termes, en programmation, ce n'est pas de l'eau qui coule, mais plutôt des données sous forme d'octets et de caractères. Nous pouvons recevoir des bits de données à partir d'un flux de données, puis les utiliser. Encore une fois, nous utiliserons l'analogie eau/débit : vous pouvez puiser de l'eau dans une rivière pour faire de la soupe, éteindre un feu ou arroser vos fleurs. Les flux vous permettent de travailler avec n'importe quelle source de données : qu'il s'agisse d'Internet, du système de fichiers de votre ordinateur ou d'autre chose, cela ne fait aucune différence. Les flux sont un outil universel. Ils permettent à un programme de recevoir des données de n'importe où (flux d'entrée) et de les envoyer n'importe où (flux de sortie). Leur tâche est la même : prendre des données d'un endroit et les envoyer à un autre. Il existe deux types de flux :- Les flux d'entrée sont utilisés pour recevoir des données
- Les flux de sortie servent à envoyer des données.
InputStream
et OutputStream
. Mais les flux peuvent être classés d'une autre manière. Outre les flux d'entrée et de sortie, on parle également de flux d'octets et de flux de caractères . La signification ici devrait être suffisamment claire : un flux d'octets envoie des informations sous la forme d'un ensemble d'octets, tandis qu'un flux de caractères les envoie sous la forme d'un ensemble de caractères. Dans cette leçon, nous nous attarderons sur les flux d'entrée. Je mettrai un lien avec des informations sur les flux de sortie à la fin de la leçon. Vous pouvez le lire par vous-même :) Maintenant, jetez un œil à ce code :
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
En parcourant les leçons, n'avez-vous pas pensé que cette réplique était assez intimidante ? :) Ce ne sera plus le cas une fois que nous aurons exploré son fonctionnement. Mettons les choses au point. Nous commencerons par la fin. System.in
est un InputStream
objet, une instance de la classe dont nous avons parlé plus tôt. Il s'agit d'un flux d'entrée lié à un périphérique d'entrée du système (le clavier). Au fait, vous connaissez indirectement ce flux. Après tout, vous utilisez fréquemment son « collègue » — System.out
! System.out
est le flux de sortie du système . Il est utilisé pour envoyer des données à la console via votre méthode préférée System.out.println()
, que vous utilisez constamment :) System.out
est un flux pour envoyer des données à la console, tandis queSystem.in
est pour obtenir des données du clavier. C'est tout simple :) De plus, nous pouvons lire les données du clavier sans cette énorme construction. On peut simplement écrire : System.in.read()
;
public class Main {
public static void main(String[] args) throws IOException {
while (true) {
int x = System.in.read();
System.out.println(x);
}
}
}
La InputStream
classe (rappelez-vous, System.in
est un InputStream
objet) a une read()
méthode qui vous permet de lire des données. Il y a un problème : il lit bytes , pas characters . Il est ennuyeux d'utiliser uniquement des lettres anglaises, alors essayons de lire le caractère chinois "魚" à partir du clavier (copiez simplement cette lettre d'ici et collez-la sur la console en utilisant ctrl + v sur PC ou Commande + v sur Mac ) . Ce caractère signifie 'un poisson' d'ailleurs. Sortie console : 233 173 154 10 Ce symbole et bien d'autres chinois occupent 3 octets dans la mémoire de l'ordinateur (contrairement aux lettres latines, qui n'occupent qu'1 octet). Dans ce cas, 4 octets sont lus à partir du flux : les trois premiers représentent le caractère "魚", et l'autre octet représente une nouvelle ligne (Entrée). En conséquence, System.in
dans sa forme sans fioritures n'est pas une option pour nous. Les humains (à de rares exceptions près !) ne savent pas lire les octets. Mais la InputStreamReader
classe vient à la rescousse ! Voyons de quel genre d'animal il s'agit.
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
Nous passons System.in
à l' objet InputStreamReader . Le nom de la classe le dit ! Nous créons un InputStreamReader
objet et lui transmettons un flux d'entrée à partir duquel il lira les données. Dans ce cas...
new InputStreamReader(System.in)
... nous lui disons, "vous lirez les données du flux d'entrée du système (du clavier)". Mais ce n'est pas sa seule fonction ! Le InputStreamReader
ne se contente pas de recevoir des données du flux. Il convertit également les flux d'octets en flux de caractères . En d'autres termes, vous n'avez plus besoin de convertir les données de "uns et zéros" en un "langage lisible par l'homme". InputStreamreader
fait tout pour vous. Bien sûr, InputStreamReader
ne se limite pas à lire les données de la console. Il peut également lire des données provenant d'autres endroits. Par exemple, à partir d'un fichier :
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
public class Main {
public static void main(String[] args) throws IOException {
InputStreamReader inputStreamReader = new InputStreamReader(new FileInputStream("C:\\Users\\username\\Desktop\\testFile.txt"));
}
}
Ici, nous créons un FileInputStream
(une variante de InputStream
), transmettons le chemin du fichier et transmettons le flux lui-même au fichier InputStreamReader
. Maintenant, il pourra lire les données du fichier (si un fichier existe réellement dans le chemin, bien sûr). Nous utilisons également la méthode InputStreamReader
de la classe read()
pour lire les données (la source des données n'a pas d'importance : la console, un fichier ou ailleurs). Quelle est la différence entre System.in.read()
et InputStreamReader.read()
?\ Essayons à nouveau de lire le caractère "魚" avec un InputStreamReader
. Je vous rappelle ce qui a été effectivement lu par System.in.read()
:
魚
233
173
154
10
Et comment fait-il InputStreamReader
le même travail ?
public class Main {
public static void main(String[] args) throws IOException {
InputStreamReader reader = new InputStreamReader(System.in);
while (true) {
int x = reader.read();
System.out.println(x);
}
}
}
Sortie console :
魚
39770
10
La différence est immédiatement apparente. Le dernier octet (représentant la nouvelle ligne) reste inchangé (le chiffre 10), mais le caractère "魚" a été converti en un seul code "39770". C'est ce que signifie lire les caractères ! Si vous ne croyez pas que 39770 représente la lettre "魚", il est facile de vous en convaincre :)
import java.io.IOException;
public class Main {
public static void main(String[] args) throws IOException {
char x = 39770;
System.out.println(x);
}
}
Sortie de la console :
魚
Mais si InputStreamReader
c'est si génial, pourquoi avons-nous aussi besoinBufferedReader
? InputStreamReader
sait lire des données et convertir des octets en caractères. Que pourrions-nous demander de plus? Pourquoi un autre lecteur ? :/ La réponse est très simple : pour plus de performances et de commodité . Commençons par les performances. Lorsqu'il BufferedReader
lit des données, il utilise une zone spéciale appelée tampon, où il "stocke" les caractères qu'il lit. En fin de compte, lorsque ces caractères seront nécessaires dans le programme, ils seront extraits du tampon, et non directement de la source de données (clavier, fichier, etc.). Cela économise beaucoup de ressources. Pour comprendre comment cela fonctionne, imaginez un coursier dans une grande entreprise. Le coursier est assis dans un bureau, attendant que quelqu'un apporte des colis à livrer. Chaque fois qu'il reçoit un nouveau colis, il peut immédiatement prendre la route. Mais il pourrait y avoir beaucoup de colis pendant la journée. Il devrait faire beaucoup de déplacements entre le bureau et les adresses de livraison. Au lieu de cela, le coursier met une boîte dans son bureau. Chacun met ses colis dans la boîte. Maintenant, le coursier peut tranquillement prendre la boîte et se déplacer d'une adresse à l'autre. Cela lui fait gagner beaucoup de temps, car il n'a pas à retourner au bureau à chaque fois. Dans cet exemple, la boîte n'est qu'un tampon et le bureau est une source de données. Il est beaucoup plus facile pour le coursier de prendre des colis dans une seule boîte lors des livraisons que de retourner au bureau à chaque fois. Il économisera aussi de l'essence. De même, dans un programme, il est beaucoup moins gourmand en ressources de prendre des données d'un tampon que de se référer à la source de données à chaque fois. Par conséquent,BufferedReader
+ InputStreamReader
est plus rapide que InputStreamReader
seul . Nous avons pensé aux performances. Qu'en est-il de la commodité? Le principal avantage est qu'il Bufferedreader
peut lire les données non seulement un caractère à la fois (bien qu'il puisse le faire avec sa read()
méthode), mais aussi des lignes entières à la fois ! Ceci est fait en utilisant la readLine()
méthode;
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
String s = reader.readLine();
System.out.println("We read this line from the keyboard:");
System.out.println(s);
}
}
Sortie console :
CodeGym est le meilleur site web pour apprendre Java !
Nous lisons cette ligne au clavier : CodeGym est le meilleur site web pour apprendre Java ! Ceci est particulièrement utile lors de la lecture de grandes quantités de données. La lecture d'une ou deux lignes de texte caractère par caractère reste possible. Mais lire dans "Guerre et Paix" une lettre à la fois serait quelque peu problématique :)
Plus de lecture : |
---|
GO TO FULL VERSION