Why use BufferedInputStream if InputStream provides read with a buffer
Why did you need to include the BufferedInputStream
wrapper in the Java I / O system, if all implementations of the InputStream
interface by default contain the read(byte b[])
method, which uses a buffer to read from the stream?
For example, I wrote a program that copies a video file of ~100 MB from one file to another.
-
Implementation using
BufferedInputStream
:public static void main (String[] args) throws IOException{ BufferedInputStream fis=new BufferedInputStream(new FileInputStream("C:/tests/1.mp4")); BufferedOutputStream fos=new BufferedOutputStream(new FileOutputStream("C:/tests/2.mp4")); int b=fis.read(); while (b!=-1){ fos.write(b); b=fis.read(); } fos.flush(); }
-
Implementation using the
read(byte b[])
{[9 method]}public static void main (String[] args) throws IOException{ FileInputStream fis=new FileInputStream("C:/tests/1.mp4"); FileOutputStream fos=new FileOutputStream("C:/tests/2.mp4"); byte[] buff=new byte[4096]; int bytes=fis.read(buff); while(bytes!=-1){ fos.write(buff, 0, bytes); bytes=fis.read(buff); } }
Implementation with using the BufferedInputStream
class is about 10 times slower than
1 answers
Try comparing the processing speed with buffering and reading the array:
BufferedInputStream fis = new BufferedInputStream(new FileInputStream("C:/tests/1.mp4"));
BufferedOutputStream fos = new BufferedOutputStream(new FileOutputStream("C:/tests/2.mp4"));
byte[] buff = new byte[4096];
int bytes = fis.read(buff);
while (bytes != -1) {
fos.write(buff, 0, bytes);
bytes = fis.read(buff);
}
fos.flush();
I believe that the processing speed will be comparable to the speed without buffering, and maybe even faster, due to the different buffer size.
Why is the first example slow
Reading / writing an array of bytes from a local file is a very fast operation. In the best case BufferedInputStream
(BufferedOutputStream
) will not affect performance in a significant way, at worst-performance will drop due to various overhead costs.
In your case, the bytes (~ 10^8) after reading from the buffer are processed one at a time, which greatly increases the overhead:
- methods
read
andwrite
are called for each byte - method calls are not free; - worse, both methods are synchronized (
synchronized
) and the VM performs a context switch/lock on each call; - in the methods themselves, there are various checks (whether it is open input / output stream, whether the buffer has run out, etc.), which also take time.
I believe that synchronization creates the main load. For the experiment, you can add synchronized methods to the option with FileInputStream
while (bytes != -1) {
for (int i = 0; i < bytes; i++) {
write(read(buff[i]));
}
fos.write(buff, 0, bytes);
bytes = fis.read(buff);
}
}
static int count = 0;
public static synchronized void write(int b) {
//неважно
count += b;
}
public static synchronized int read(int b) {
return count + b;
}
Why BufferedInputStream
Buffered streams are needed to avoid writing buffering yourself. They also allow you to separate the program logic from the buffering settings. BufferedInputStream
is especially useful if:
The algorithm is used, which processes bytes sequentially. In this case, you can simplify the code by entrusting buffering to the built-in class.
-
The stream itself is used as an argument for the reader class.
For example,
BufferedInputStream
can be passed as an argument toScanner
:Scanner scanner = new Scanner(new BufferedInputStream(new FileInputStream("input")));
After that, using
Scanner
, you can work with the data line by line, andBufferedInputStream
will save on accessing the file system. -
Specific methods are used.
Methods
InputStream.mark
andInputStream.reset
, typically not available in unbuffered streams. Accordingly, if you need to roll back the state of the stream, you will not be able to useFileInputStream
.
Using the example of copying a file, it is difficult to see the advantages. On the other hand, it is better to use built-in methods rather than threads to copy a file.