Here is an example

public static void main(String[] args) throws Exception { FileInputStream inputStream = new FileInputStream("c:/data.txt"); FileOutputStream outputStream = new FileOutputStream("c:/result.txt"); byte[] buffer = new byte[1000]; while (inputStream.available() > 0){ int count = inputStream.read(buffer); outputStream.write(buffer, 0, count); } inputStream.close(); outputStream.close(); } 

Here are a few questions.

  1. Why do I need to specify outputStream.write(buffer, 0, count); the number of bytes to write (from and to 0, count ), if the read(byte[] byte) method still reads bytes until the buffer is full or the bytes in the file run out.

    I understand that how many bytes were given so much and wrote outputStream.write(buffer); Why put it inside out?

  2. Why specify a buffer when BufferedInputStream() is present? If I understand correctly, it will work as well as if we specify byte[] byte = new byte[1000] ... It will also buffer bytes before writing ....

EDIT

Concerning my second question, here is a method for an example.

 private void writeFile(File file, byte[] bytes) { BufferedOutputStream bos = null; try { bos = new BufferedOutputStream(new FileOutputStream(file)); bos.write(bytes); } catch (IOException e) { e.printStackTrace(); } finally { if (image != null) { image.close(); } if (null != bos) { try { bos.close(); } catch (IOException e) { e.printStackTrace(); } } } } 

EDIT2

enter image description here

  • And if you want to write not the entire buffer ? - post_zeew
  • BufferedOutputStream does not have a write method with such a signature. Completed the answer - selya

2 answers 2

  1. The write(byte[] data) or write(byte[] data, int offset, int length) FileOutputStream and BufferedOutputStream classes still need to specify an array of read bytes to write the array, so in any case they will need to be read before writing the bytes into the internal buffer. So using BufferedInputStream instead of FileInputStream does not release the need to read data into the internal buffer.
    Moreover, if you do not use the specific capabilities of the buffered streams, the code for working with buffered and unbuffered streams will be generally the same.
    Another thing is that in most cases working with buffered threads will be an order of magnitude faster.
  2. In your reasoning you forget that the last (and perhaps the only) fragment of the input file does not have to match the size of the buffer in size, so in any case, when writing the last fragment, you need to specify how many bytes should be written - namely, so much how much was actually read. Otherwise, when writing to the end of the file, excess garbage will be assigned, which was not in the input file (in the case of a single fragment, these will be zeros, and in the case of a non-unique fragment, a part of the previous fragment will be rewritten).
    Therefore, in any case, it will be necessary to use write(byte[] data, int offset, int length) to write at least one (last) fragment, and using different methods to write the last and not the last fragments is an unnecessary complication of the code.
  • Any InputStream has a method with a read(byte[]) signature that reads the number of bytes that can fit into this buffer, or less if less is available, and returns the number of characters read, edit - selya
  • Yes, of course, the shame on my gray head - I do not know what I was thinking. I'll fix it now. - m. vokhm

By creating an array of bytes, you emit 1000 bytes in a heap, which java kindly floods you with zeros. Those. in this line: byte[] buffer = new byte[1000]; you say: please fill me 1000 bytes with zeros and save the reference to the array in the variable buffer.

When you call the is.read(buffer) method, it reads the number of bytes that could be read . And after that it returns the number of bytes that it read, which you save to the count variable.

After these manipulations, you will have an array of 1000 bytes, the count of which will be filled with read values, and the remaining bytes will be zeros .

In order not to write unnecessary zeros to the file, which in fact was not in the source file, you say: os.write(buffer, 0, count) , which is equivalent: please fill me with bytes from the buffer buffer starting at 0 , total count pieces.

And in BufferedOutputStream there is no write method with a signature (byte[]) .

Again. Since the output stream has no idea, if you want to write the entire array of bytes or parts into it, it asks you for the starting position and the number of bytes that are to be written. Understand. This is done for convenience. You can read anywhere bytes from the InputStream , create the correct array of the desired length, copy the necessary values ​​into it and transfer the whole array to the record without specifying the initial position and number of bytes, but these are:

  1. Not rational. It takes processor time and an extra piece of memory to create an array of the desired length.

  2. Not convenient, since a lot of excess code.

Those. to draw a line: with this api, you can create some buffer of size n and reuse it as many times as you like to read bytes from the stream, and the count variable will tell you how many valid bytes are currently in your buffer. And also: when reading from a stream in a cycle, consider that a smaller number of bytes can be read than the size of your buffer. And the count variable will talk about how many bytes have been read.

Something like this

  • The second question is that you can write like this new BufferedInputStream(new FileInputStriam(fileName)); in essence, the BufferedInputStream will create a buffer and read it in portions, then why read these portions of bytes and then relocate them to the buffer? - Aleksey Timoshchenko
  • 1. RAM. If you were copying 1GB files on your system with 2GB RAM using BufferedInputStream , then I would like to wish you good luck. 2. The taste and color ... - selya
  • So to prevent OOM? - Aleksey Timoshchenko
  • A buffered stream simply gives you the opportunity to return to what has been read. While it is stored in the operative. If I’m not mistaken, there are some other optimizations for reading, but if you read in portions, and you don’t call read for one byte, you don’t feel it. And to write these bytes in the OutputStream , you still have to get an array buffer, and write it down. Those. in fact, you compared two different things. If it helped, then I will add more detailed material to the answer. - selya
  • Did not quite understand what you said 1. дает вам возможность вернуться к тому, что было прочитано - where to return? 2. При том это хранится в оперативе - in the sense of when I add a BufferedInputStream - does it save in operative? And if I do not use it does not save? 3. читаете порциями, а не делаете вызоа read для одного байта, то не почувствуете - you do not understand the comparison ... in which case there will be no difference? 4. ам все равно придется получить массив-буфер — why? If I can use BufferedOutputStream .? - Aleksey Timoshchenko