Got two questions.
What does actually the program do if coded bis.read() instead of bis.read(bys)? (It works at any rate though much slower.)
Why is bos.write(bys) much faster than bos.write(bys, 0, len)? (I expected that both are same in speed in run.)
Thanks!
public class CopyFileBfdBytes {
public static void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream("d:/Test1/M1.MP3");
BufferedInputStream bis = new BufferedInputStream(fis);
FileOutputStream fos = new FileOutputStream("d:/Test2/M2.mp3");
BufferedOutputStream bos = new BufferedOutputStream(fos);
byte[] bys = new byte[8192];
int len;
while ((len = bis.read(bys)) != -1){
// while ((len = bis.read()) != -1){ // 1. Why does it still work when bys in bis.read() is missing?
bos.write(bys);
// bos.write(bys, 0, len); // 2. Why is this slower than bos.write(bys)?
bos.flush();
}
fis.close();
bis.close();
fos.close();
bos.close();
}
}
First of all, it seems like you simply want to copy a file as-is. There are much simpler (and maybe even more performant approaches) to do this.
Other approaches to copy data
Copying files
If everything you need is to copy actual Files like in your example, you could simply use:
This is most likely the most descibring (e.g. other devs actually see what you want to do) and can be done very efficient by the underlyingsystem.
Copying data from any source to any destination (InputStream to OutputStream)
If you need to transfer data from any InputStream to any OutputStream you could use the method
InputStream#transferTo(OutputStream):Describing your question in-depth
Note: I will talk about
InputStreams andOutputStreams in general. You usedBufferedInputStreamandBufferedOutputStream. Those are specific implementations that internally buffer data. This internal buffering has nothing to do with the buffering I will talk about next!InputStream
There is a fundamental difference between
InputStream#read()andInputStream#read(byte[]).InputStream#read()reads one byte from the InputStream and returns it. The returned value is anintin the range of0-255or-1if the Stream is exhausted (there is no more data).InputStream#read(byte[])however, is completely different. It takes anbyte[]as a parameter that is being used as a buffer. It then (internally) tries to fill the given buffer with as much bytes as it can obtain at the moment and returns the actual number of bytes that it has filled or-1if the Stream is exhausted.Example:
Bad example: Now a bad example. The following code contains programming-errors, so don't use this!
We now loop from
0tobuffer.length, but our input-data contains exactly9bytes. That means, in the last iteration our buffer will only be filled with one byte. The second byte in our buffer will not be touched.OutputStream
Now that I described what the differences in reading are, I'll describe you the differences in writing.
First, the correct example (using
OutputStream.write(byte[], int, int)):And the bad example:
This is because, just like in our examples with the
InputStream, if we ignore thebytesRead, we will write one value to ourOutputStreamthat we don't want: the byte8from the previous iteration. This is because internally,OutputStream#write(byte[])is (in most implementations) just a shortcut forOutputStream.write(buffer, 0, buffer.length). That means it writes to whole buffer to theOutputStream.