"Hello, Amigo! Today we're going to once again dig into how InputStream and OutputStream work. The initial explanation was actually a little simplistic. These are not interfaces. They are abstract classes, and they even have a couple of implemented methods. Let's take a look at the methods they have:"

InputStream methods What the method does
int read(byte[] buff);
This method immediately reads a block of bytes into the buffer (byte array), until the buffer is full or until the source doesn't have any more bytes to read.
The method returns the number of bytes actually read (which can be less than the length of the array)
int read();
This method reads one byte and returns it. The result is widened to an int for looks. If there are no more bytes to read, the method returns -1.
int available();
This method returns the number of unread (available) bytes.
void close();
This method «closes» the stream. You call this when you're done working with the stream.
The object then performs the housekeeping operations needed to close the file, etc.
At this point, you can't read any more data from the stream.

"So we can read not only single bytes, but also whole blocks?"

"Exactly."

"Can we also write whole blocks?"

"Yes, check it out:"

OutputStream methods What the method does
void write(int c);
This method writes one byte. The int type is narrowed to a byte. The extra part is simply discarded.
void write(byte[] buff);
This method writes a block of bytes.
void write(byte[] buff, int from, int count);
This method writes part of a block of bytes. It is used in cases when the byte array may not have been filled entirely.
void flush();
If the stream is internally storing any data that has not yet been written, this method forces it to be written.
void close();
This method «closes» the stream. You call this when you're done working with the stream.
The object then performs the housekeeping operations needed to close the file, etc. You can't write data to the stream any longer, and flush is called automatically.

"What would the file copying code look like if we read whole blocks at a time instead of single bytes?"

"Hmm. Something like this:"

Copy a file on disk
public static void main(String[] args) throws Exception
{
 //Create a stream to read bytes from a file
 FileInputStream inputStream = new FileInputStream("c:/data.txt");
 //Create a stream to write bytes to a file
 FileOutputStream outputStream = new FileOutputStream("c:/result.txt");

  byte[] buffer = new byte[1000];
 while (inputStream.available() > 0) //as long as there are unread bytes
 {
  //Read the next block of bytes into buffer, and store the actual number of bytes read in count.
  int count = inputStream.read(buffer);
  outputStream.write(buffer, 0, count); //Write a block (part of a block) to the second stream
 }

 inputStream.close(); //Close both streams. We don't need them any more.
 outputStream.close();
}

"I understand everything about the buffer, but what's this count variable?"

"When we read the latest block of data from a file, we may get, say, 328 bytes instead of 1000. So when we write the data, we need to indicate that we're not writing the entire block—only the first 328 bytes."

When we read the last block, the read method will return the number of bytes actually read. 1000 every time we read a block, except for the last block, when we get 328.

So when we write a block, we indicate that not all of the bytes in the buffer should be written, just 328 (i.e. the value stored in the count variable).

"Now it's all clear. Thanks, Ellie."