Copying a file using InputStream and OutputStream


Copying a file

We can directly copy data from a source to a data sink using a loop. In this example, we are reading data from an InputStream and at the same time, writing to an OutputStream. Once we are done reading and writing, we have to close the resource.

public void copy(InputStream source, OutputStream destination) throws IOException {
	try {
		int c;
		while ((c = source.read()) != -1) {
			destination.write(c);
		}
	} finally {
		if (source != null) {
			source.close();
		}
		if (destination != null) {
			destination.close();
		}
	}
}

Reading from a binary file

You can read an a binary file using this piece of code in all recent versions of Java:

//Version ≥ Java SE 1.4
File file = new File("path_to_the_file");
byte[] data = new byte[(int) file.length()];
DataInputStream stream = new DataInputStream(new FileInputStream(file));
stream.readFully(data);
stream.close();
 
If you are using Java 7 or later, there is a simpler way using the nio API:
 
//Version ≥ Java SE 7
Path path = Paths.get("path_to_the_file");
byte [] data = Files.readAllBytes(path);

Reading a file using Channel and Buer

Channel uses a Buffer to read/write data. A buffer is a fixed sized container where we can write a block of data at once. Channel is a quite faster than stream-based I/O.

To read data from a file using Channel we need to have the following steps:

  • We need an instance of FileInputStream. FileInputStreamhas a method named getChannel() which returns a Channel.
  • Call the getChannel() method of FileInputStream and acquire Channel.
  • Create a ByteBuffer. ByteBuffer is a fixed size container of bytes.
  • Channel has a read method and we have to provide a ByteBuffer as an argument to this read method. ByteBuffer has two modes - read-only mood and write-only mood. We can change the mode using flip() method call. Buffer has a position, limit, and capacity. Once a buffer is created with a fixed size, its limit and capacity are the same as the size and the position starts from zero. While a buffer is written with data, its position gradually increases. Changing mode means, changing the position. To read data from the beginning of a buffer, we have to set the position to zero. flip() method change the position
  • When we call the read method of the Channel, it fills up the buffer using data.
  • If we need to read the data from the ByteBuffer, we need to flip the buffer to change its mode to write-only to read-only mode and then keep reading data from the buffer.
  • When there is no longer data to read, the read() method of channel returns 0 or -1.
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
 
public class CustomFileChannelRead {
    public static void main(String[] args) {
        File customInputFile = new File("example.txt");
        if (!customInputFile.exists()) {
            System.out.println("The custom input file doesn't exist.");
            return;
        }
 
        try {
            FileInputStream customFileInputStream = new FileInputStream(customInputFile);
            FileChannel customFileChannel = customFileInputStream.getChannel();
            ByteBuffer customBuffer = ByteBuffer.allocate(1024);
 
            while (customFileChannel.read(customBuffer) > 0) {
                customBuffer.flip();
                while (customBuffer.hasRemaining()) {
                    byte customByte = customBuffer.get();
                    System.out.print((char) customByte);
                }
                customBuffer.clear();
            }
 
            customFileChannel.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

Adding Directories

To make a new directory from a File instance you would need to use one of two methods: mkdirs() or mkdir().

  • mkdir() - Creates the directory named by this abstract pathname.
  • mkdirs() - Creates the directory named by this abstract pathname, including any necessary but nonexistent parent directories. Note that if this operation fails it may have succeeded in creating some of the necessary parent directories.

Note : createNewFile() will not create a new directory only a file.

import java.io.File;
import java.io.IOException;
 
public class CustomFileCreation {
    public static void main(String[] args) throws IOException {
        File firstDirectory = new File("C:/Users/ExampleUser/Desktop/My New Directory/");
 
        File secondDirectory = new File("C:/Users/ExampleUser/Desktop/My New Directory 2/Another Folder/");
        // Assume that neither "My New Directory" nor "My New Directory 2" exist
 
        firstDirectory.createNewFile(); // Will create a new file called "My New Directory.file"
        firstDirectory.mkdir(); // Will create the directory
        firstDirectory.mkdirs(); // Will create the directory
 
        // Attempting to create a file in a non-existent directory will throw IOException
        // secondDirectory.createNewFile(); // This line is commented out to avoid exception
 
        // Attempting to create a directory directly will not work
        // secondDirectory.mkdir(); // This line is commented out to avoid failure
 
        // Creating the directory and its parent directories
        secondDirectory.mkdirs(); // Will create the directory
    }
}
 

Basic Programs