JavaRush /Java Blog /Random EN /Reading from the keyboard - "readers"

Reading from the keyboard - "readers"

Published in the Random EN group
Hello! In lectures and tasks, we learned how to output data to the console, and vice versa - read data from the keyboard. Reading from the keyboard - “readers” - 1You even learned to use a complex construction for this:
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
But we still haven’t answered one question.

How does this even work?

In fact, any program most often does not exist on its own. It can communicate with other programs, systems, the Internet, etc. By the word “communicate” we first of all mean “exchange data”. That is, receive some data from the outside, and, on the contrary, send your own data somewhere. There are many examples of data exchange between programs, even in everyday life. So, on many sites, instead of registering, you can log in using your Facebook or Twitter account. In this situation, two programs, say, Twitter and the site where you are trying to register, exchange the necessary data with each other, after which you see the end result - successful authorization. The term “ flow ” is often used to describe the process of data exchange in programming . Where did this name even come from? “Flow” is more associated with a river or stream than with programming. In fact, this is not without reason :) A stream is, in essence, a moving piece of data. That is, in programming, it is not water that “flows” along the stream, but data in the form of bytes and characters. From a data stream, we can receive data in parts and do something with it. Again, let’s use the “water-flowing” analogy: you can scoop water from a river to cook soup, put out a fire, or water flowers. Using streams, you can work with any data source: the Internet, the file system of your computer, or something else - it doesn’t matter. Streams are a universal tool. They allow the program to receive data from anywhere (incoming streams) and send it anywhere (outgoing streams). Their task is one - to take data in one place and send it to another. Streams are divided into two types:
  1. Incoming stream ( Input ) - used to receive data
  2. Outgoing stream ( Output ) - for sending data.
The incoming data flow in Java is implemented in the class InputStream, and the outgoing data flow in the class OutputStream. But there is another way to divide threads. They are divided not only into incoming and outgoing, but also into byte and character . Here the meaning is clear without explanation: a byte stream transmits information in the form of a set of bytes, and a character stream transmits information in the form of a set of characters. In this lecture we will go into detail about incoming streams. And I will attach information about outgoing links at the end, and you can read about it yourself :) So, our code:
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
You probably thought while reading the lectures that it looked quite scary? :) But this is only until we figure out how this thing works. Let's fix it now! Let's start from the end. System.inis an object of the class InputStreamthat we talked about at the beginning. This is an incoming stream, and it is tied to the system input device - the keyboard. By the way, you are indirectly familiar with him. After all, you often use his “colleague” in your work - System.out! System.out- this is a system data output stream , it is used for output to the console in the very method System.out.println()that you constantly use :) System.out- a stream for sending data to the console, and System.in- for receiving data from the keyboard. It's simple :) Moreover: to read data from the keyboard, we can do without this large construction and simply write: 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);
       }
   }
}
In the class InputStream(and System.in, let me remind you, is an object of the class InputStream) there is a method read()that allows you to read data. One problem: it reads bytes , not characters . Let's try to read the Russian letter “Ya” from the keyboard. Console output:
Я
208
175
10
Russian letters take up 2 bytes in the computer's memory (unlike English letters, which take up only 1). In this case, 3 bytes were read from the stream: the first two represent our letter “I”, and the other one is the line break (Enter). Therefore, the option to use “naked” System.inwill not suit us. Humans (with rare exceptions!) cannot read bytes. This is where the next class comes to our aid - InputStreamReader! Let's figure out what kind of animal this is.
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
We pass the stream System.into the InputStreamReader. In general, if you translate its name into Russian, everything looks obvious - “reader of incoming streams”. Actually, that’s exactly what it’s for! We create a class object InputStreamReaderand pass it an incoming stream from which it should read data. In this case...
new InputStreamReader(System.in)
...we tell it: “you will read data from the system input stream (keyboard).” But this is not its only function! InputStreamReadernot only receives data from the stream. It also converts byte streams to character streams . In other words, you no longer need to worry about translating the read data from “computer” language into “human” language - InputStreamReaderit will do everything for you. InputStreamReader, of course, can read data not only from the console, but also from other places. For example, from the file:
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"));
   }
}
Here we created an incoming data stream FileInputStream(this is one of the varieties InputStream), passed the path to the file into it, and passed the stream itself InputStreamReader'y. Now it will be able to read data from this file, if the file at this path exists, of course. To read data (no matter from where, from the console, a file, or anywhere else), the class InputStreamReaderalso uses the read(). What is the difference between System.in.read()and InputStreamReader.read()? Let's try to count the same letter “I” using InputStreamReader. Let me remind you, this is what I thought System.in.read():
Я
208
175
10
How can he do the same job InputStreamReader?
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);
       }
   }
}
Console output:
Я
1071
10
The difference is immediately visible. The last byte - for line breaks - remained unchanged (the number 10), but the read letter “I” was converted into a single code “1071”. This is reading by symbols! If you suddenly don’t believe that code 1071 means the letter “I”, you can easily verify this :)
import java.io.IOException;

public class Main {

   public static void main(String[] args) throws IOException {

       char x = 1071;
       System.out.println(x);
   }
}
Console output:

Я
But if InputStreamReaderit’s so good, why do you need more BufferedReader? InputStreamReadercan both read data and convert bytes into characters - what else do we need? Why another Reader? :/ The answer is very simple - for greater productivity and greater convenience . Let's start with performance. When reading data, BufferedReader uses a special area - a buffer, where it “adds” the read characters. As a result, when we need these characters in the program, they will be taken from the buffer, and not directly from the data source (keyboard, file, etc.), and this saves a lot of resources. To understand how this works, imagine, for example, the work of a courier in a large company. The courier sits in the office and waits for parcels to be brought to him for delivery. Each time he receives a new parcel, he can immediately hit the road. But there may be a lot of parcels during the day, and he will have to travel between the office and addresses each time. Instead, the courier placed a box in the office where everyone could put their parcels. Now the courier can calmly take the box and go to the addresses - he will save a lot of time, because he will not have to return to the office every time. The box in this example is precisely the buffer, and the office is the data source. It is much easier for a courier to take a letter from a common box when delivering it than to go to the office every time. It will also save gas. It’s the same in a program - it’s much less resource-intensive to take data from the buffer, rather than accessing the data source every time. That's why BufferedReader+ InputStreamReaderworks faster than just InputStreamReader. We've sorted out the performance, but what about convenience? The main advantage is that BufferedReaderit can read data not only one character at a time (although read()it also has a method for this purpose), but also entire lines! This is done using the readLine();
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);
   }
}
Console output:
JavaRush is the best site to learn Java!
Мы считали с клавиатуры эту строку:
JavaRush — лучший сайт для изучения Java!
This is especially useful when reading a large amount of data. One or two lines of text can still be read character by character. But counting “War and Peace” one letter at a time will be somewhat problematic :) Now the work of threads has become much more clear to you. For further study, here is an additional source for you: Here you can read more about incoming and outgoing flows. Video review BufferedReaderfrom one of our students. Yes, yes, our students not only learn themselves, but also record educational videos for others! Don't forget to like and subscribe to our channel :)
It is better to accustom yourself to reading official documentation from the very beginning of your studies. It is the main source of knowledge about the language, and most of the answers can always be found there.
Comments
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION