"We'll start with streams for file input/output. But first things first."

There are two classes for reading and writing files: FileInputStream and FileOutputStream. As you probably already guessed, FileInputStream can sequentially read bytes from a file, and FileOutputStream can sequentially write bytes to a file. Here are the methods that these classes have:

Method What the method does
FileInputStream(String fileName);
— This is the constructor. It lets you specify the name of a file on disk, from which the created object will read data.
int read();
— This method reads one byte from the file and returns it. The return value is widened to an int.
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.

Just for the fun of it, let's calculate the sum of all the bytes in a file. Here's what the code looks like:

Sum up all the bytes in a file
public static void main(String[] args) throws Exception
{
 //Create a FileInputStream object bound to «c:/data.txt».
 FileInputStream inputStream = new FileInputStream("c:/data.txt");
 long sum = 0;

 while (inputStream.available() > 0) //as long as there are unread bytes
 {
  int data = inputStream.read(); //Read the next byte
  sum +=  data; //Add it to the running total
 }
 inputStream.close(); // Close the stream

 System.out.println(sum); // Display the sum on the screen.
}

"We've already looked into something like this. How is FileOutputStream organized?"

"OK. Look at this:"

Method What the method does
FileOutputStream (String fileName);
"This is the constructor. It lets you specify the name of a file on disk, to which the created object will write data."
void write(int data);
"This method writes the next byte, truncating data to one byte."
void flush();
"The data to be written is often first collected in large blocks in memory, and then only written to disk."

The flush command forces all unsaved information to be written to disk.

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.

"That's it?"

"Yep, there's actually only one method for writing: write(). It writes only one byte at a time. But it lets you write as much information as you want to the file."

Programming is a process of dividing one large and complex task into many small ones. Essentially the same process is happening here: reading and writing large blocks of data is broken into reading and writing in bite-sized pieces—one byte at a time.

Here's how you can use these classes to copy a file on disk:

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");

 while (inputStream.available() > 0) //as long as there are unread bytes
 {
  int data = inputStream.read(); // Read the next byte into the data variable
  outputStream.write(data); // and write it to the second stream
 }

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

"Thanks, Rishi. I finally understand how this code actually works."