1. InputStreamReader
class
Another interesting feature of streams is that you can combine multiple streams together into chains. A stream can read data not only from its internal data source, but also from another stream.
This is a very powerful mechanism in Java, which makes it possible to create complex data reading scenarios by connecting one stream to another. Such a scheme looks like this:
When a program reads data from a data stream, the data stream in turn reads the data from its data source, which is another data stream or a file, for example.
What's more, each data stream not only reads in and gives out data, but can also transform it or perform various operations on it. A good example of such an "intermediate stream" is the InputStreamReader
class.
We already know a class called FileReader
— it is a Reader
that reads data from a file. And where does InputStreamReader
get its data from? That's right — from an InputStream
.
When you create an InputStreamReader
object, you need to pass in an InputStream
object or one of its descendant classes. Example:
String src = "c:\\projects\\log.txt";
FileInputStream input = new FileInputStream(src);
InputStreamReader reader = new InputStreamReader(input);
The InputStreamReader
class has all the methods that the Reader
class has, and they work in exactly the same way.
The main difference between the InputStreamReader
class and, say, FileReader
is where they read data from. FileReader
reads data from a file (duh — that's why it's called FileReader
), but InputStreamReader
reads data from an InputStream
.
When you read a character from a FileReader
object using the read()
method, it in turn reads two bytes from the file on disk and returns them as chars
.
When you read a character from an InputStreamReader
object using the read()
method, it in turn reads two bytes from the FileInputStream
object passed to it, which in turn reads data from the file. The result is a chain of calls to read()
methods.
2. BufferedReader
class
Another interesting class that you are likely to use a lot is BufferedReader
. This is also an "intermediate stream" that reads data from another stream.
As its name suggests, the BufferedReader
class is a subclass of Reader
and lets you read characters. But what is most interesting is that you also need to pass it a data source in the form of a stream from which characters can be read, i.e. a stream that inherits the Reader
class.
What's the point? Unlike InputStreamReader
, the BufferedReader
class does not convert bytes to characters: it doesn't convert anything at all. Instead, it buffers data.
When a program reads a single character from a BufferedReader
object, the object reads a large array of characters from its source stream all at once. And stores them internally.
When the next character is read from the BufferedReader
object, it simply grabs the next character from its internal buffer array and returns it without accessing the data source. Only when all the characters in the buffer are used up does it read in another large array of characters.
The BufferedReader
class also has a very useful method — String readLine()
, which lets you read entire strings of data from the source stream all at once. You can use this method to, say, read a file and display its contents on the screen line by line. Example:
We specifically wrote some compact code to illustrate how convenient this can be. This code could also be written with a little more detail.
|
Create a FileReader object. The data source is a file.Create a BufferedReader object. The data source is a FileReader .As long as there is still data in the reader Read one line Display the line |
If you chain together multiple streams, then the close()
method only needs to be called on one of them. That stream will call the method on its data source, and so on, until close()
is called on the final data stream.
3. Reading from the console
And one more interesting fact: the Scanner
class is nothing more than an intermediate input stream that reads data from System.in
, which is also a data stream.
Here are two ways to read a line from the console:
Scanner class | BufferedReader and BufferedWriter classes |
---|---|
|
|
Our friend System.in
is nothing more than a static in
variable of the System
class. It is an InputStream
whose name is in
.
So almost from the very beginning of your Java studies on CodeGym, you have been working with data streams and build chains from them. But now you will do it more consciously.
GO TO FULL VERSION