JavaRush /Java Blog /Random EN /I/O in Java. Classes FileInputStream, FileOutputStream, B...

I/O in Java. Classes FileInputStream, FileOutputStream, BufferedInputStream

Published in the Random EN group
Hello! In today's lecture we will continue the conversation about input and output streams in Java, or Java I/O (“input-output”) for short. This is not the first lecture on this topic, and it will not be the last :) It just so happens that Java as a language provides many opportunities for working with input/output. There are quite a lot of classes that implement this functionality, so we divided them into several lectures so that you don’t get confused at first :) I/O in Java.  Classes FileInputStream, FileOutputStream, BufferedInputStream - 1In previous lectures we touched on BufferedReader , as well as the abstract classes InputStream & OutputStream and several descendants. Today we will look at 3 new classes: FileInputStream , FileOutputStream and BufferedInputStream .

FileOutputStream class

The main purpose of the FileOutputStream class is to write bytes to a file. Nothing complicated :) FileOutputStream is one of the implementations of the abstract OutputStream class . In the constructor, objects of this class take either the path to the target file (to which the bytes need to be written) or an object of the class File. Let's look at both examples:
public class Main {

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


       File file = new File("C:\\Users\\Username\\Desktop\\test.txt");
       FileOutputStream fileOutputStream = new FileOutputStream(file);

       String greetings = "Hi! Welcome to JavaRush - the best site for those who want to become a programmer!";

       fileOutputStream.write(greetings.getBytes());

       fileOutputStream.close();
   }
}
When creating an object, Filewe specified in the constructor the path where it should be located. There is no need to create it in advance: if it does not exist, the program will create it itself. You can do without creating an extra object and just pass a string with the address:
public class Main {

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


       FileOutputStream fileOutputStream = new FileOutputStream("C:\\Users\\Username\\Desktop\\test.txt");

       String greetings = "Hi! Welcome to JavaRush - the best site for those who want to become a programmer!";

       fileOutputStream.write(greetings.getBytes());

       fileOutputStream.close();
   }
}
The result in both cases will be the same. We can open our file and see there:

Hello! Добро пожаловать на JavaRush — лучший сайт для тех, кто хочет стать программистом!
However, there is one caveat here. Try running the code from the example above several times in a row, and then look at the file and answer the question: how many lines do you see written in it? Just one. But you ran the code several times. However, it turns out that the data was overwritten each time, replacing the old ones. What if we are not satisfied with this and need sequential recording? What if we want to write our greeting to a file three times in a row? Everything is simple here. Since the language itself cannot know what kind of behavior we need in each case, FileOutputStreamyou can pass an additional parameter to the constructor - boolean append. If its value is true , the data will be written to the end of the file. If false (and the default value is false ), old data will be erased and new data will be written. Let's test and run our modified code three times:
public class Main {

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


       FileOutputStream fileOutputStream = new FileOutputStream("C:\\Users\\Username\\Desktop\\test.txt", true);

       String greetings = "Hi! Welcome to JavaRush - the best site for those who want to become a programmer!\r\n";

       fileOutputStream.write(greetings.getBytes());

       fileOutputStream.close();
   }
}
Result in file:

Hello! Добро пожаловать на JavaRush - лучший сайт для тех, кто хочет стать программистом!
Hello! Добро пожаловать на JavaRush - лучший сайт для тех, кто хочет стать программистом!
Hello! Добро пожаловать на JavaRush - лучший сайт для тех, кто хочет стать программистом!
Another thing! Keep this feature in mind when using I/O classes. At one time, I had to sit for hours on tasks to understand where my old data went from the files :) And of course, as in the case of other I/O classes, do not forget about releasing resources through the close().

FileInputStream class

The class has FileInputStreamthe opposite purpose - reading bytes from a file. Just like FileOutputStreaminherits OutputStream, this class derives from the abstract class InputStream. Let's write several lines of text into our text “ test.txt ”:

«So close no matter how far
Couldn't be much more from the heart
Forever trusting who we are
And nothing else matters»
I/O in Java.  Classes FileInputStream, FileOutputStream, BufferedInputStream - 2 This is what the implementation of reading data from a file using FileInputStream:
public class Main {

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

       FileInputStream fileInputStream = new FileInputStream("C:\\Users\\Username\\Desktop\\test.txt");

       int i;

       while((i=fileInputStream.read())!= -1){

           System.out.print((char)i);
       }
   }
}
We read one byte from the file, convert the read bytes into characters and output them to the console. And here is the result in the console:

So close no matter how far
Couldn't be much more from the heart
Forever trusting who we are
And nothing else matters

BufferedInputStream class

I think, given the knowledge from previous lectures, you can easily tell why the class is needed BufferedInputStreamand what advantages it has over FileInputStream:) We have already met with buffered streams, so try to guess (or remember) before continuing reading :) Buffered streams are needed primarily to optimize I/O. Accessing a data source, such as reading from a file, is a performance-intensive operation. And accessing the file to read one byte each time is wasteful. Therefore, BufferedInputStreamit reads data not one byte at a time, but in blocks and temporarily stores them in a special buffer. This allows us to optimize the operation of the program by reducing the number of accesses to the file. Let's see what it looks like:
public class Main {

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

       FileInputStream fileInputStream = new FileInputStream("C:\\Users\\Username\\Desktop\\test.txt");

       BufferedInputStream bufferedInputStream = new BufferedInputStream(fileInputStream, 200);

       int i;

       while((i = bufferedInputStream.read())!= -1){

           System.out.print((char)i);
       }
   }
}
Here we have created an object BufferedInputStream. It accepts an object or any of its successors as input InputStream, so the previous one FileInputStreamwill do. It takes the buffer size in bytes as an additional parameter. Now, thanks to this, data will be read from the file not one byte at a time, but 200 at a time! Imagine how much we have reduced the number of file accesses. To compare performance, you can take some large text file several megabytes in size and compare how long it takes to read it and output it to the console in milliseconds using FileInputStreamand BufferedInputStream. Here are both examples of code:
public class Main {

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

       Date date = new Date();

       FileInputStream fileInputStream = new FileInputStream("C:\\Users\\Username\\Desktop\\textBook.rtf");

       BufferedInputStream bufferedInputStream = new BufferedInputStream(fileInputStream);

       int i;

       while((i = bufferedInputStream.read())!= -1){

           System.out.print((char)i);
       }

       Date date1 = new Date();

       System.out.println((date1.getTime() - date.getTime()));
   }
}



public class Main {

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

       Date date = new Date();

       FileInputStream fileInputStream = new FileInputStream("C:\\Users\\Username\\Desktop\\26951280.rtf");


       int i;

       while((i = fileInputStream.read())!= -1){

           System.out.print((char)i);
       }

       Date date1 = new Date();

       System.out.println((date1.getTime() - date.getTime()));
   }
}
When reading a 1.5 MB file on my computer, FileInputStreamit did the job in ~3500 milliseconds, but here BufferedInputStreamit did the job in ~1700 milliseconds. As you can see, the buffered stream optimized the program's performance by 2 times! :) We will continue to study I/O classes - see you soon!
Comments
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION