Java NIO FileChannel transferTo() and transferFrom()

When using FileChannel transferTo() and transferFrom() methods, data doesn’t pass through the Java heap, thus reducing garbage collection pressure.

In Java applications, standard IO happens mostly between an input source and output target. Similarily, in NIO as well we may need to transfer data from one channel to another channel very frequently. The FileChannel class in Java NIO provides efficient data transfer methods using the methods transferTo() and transferFrom().

When using FileChannel transferTo() and transferFrom() methods, data doesn’t pass through the Java heap, thus reducing garbage collection pressure.

1. Data Transfer between Channels

Bulk transfers of file data from one place to another are so common that a couple of optimization methods have been added to the FileChannel class to make it even more efficient. Two such methods are:

  • FileChannel.transferTo()
  • FileChannel.transferFrom()

These methods are commonly used for high-performance file I/O operations to move data between file channels or between a file channel and other types of channels (e.g., socket channels).

The transferTo() and transferFrom() methods allow us to cross-connect one channel to another, eliminating the need to pass the data through an intermediate buffer.

These methods exist only in the FileChannel class, so one of the channels involved in a channel-to-channel transfer must be a FileChannel.

public abstract class FileChannel
        extends AbstractChannel
        implements ByteChannel, GatheringByteChannel, ScatteringByteChannel {

        // ... more methods ...
        public abstract long transferTo (long position, long count, WritableByteChannel target);
        public abstract long transferFrom (ReadableByteChannel src, long position, long count);
}

We can’t do direct transfers between socket channels, but socket channels implement WritableByteChannel and ReadableByteChannel, so the content of a file can be transferred to a socket with transferTo(), or data can be read from a socket directly into a file with transferFrom().

Also, keep in mind that these methods may throw java.io.IOException if any error is encountered during the transfer.

Channel-to-channel transfers can potentially be extremely fast, especially where the underlying operating system provides native support. Some operating systems can perform direct transfers without ever passing the data through user space. This can be a huge win for high-volume data transfer.

2. FileChannel transferTo() and transferFrom() Examples

2.1. Simple File Copy Example

The follwoing program shows the use of both transferTo() and transferFrom() methods for copying a file. You can uncomment the desired method for use.

import java.io.IOException;
import java.nio.channels.FileChannel;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;

public class FileCopyExample {

    public static void main(String[] args) throws IOException {

        try (FileChannel sourceChannel = FileChannel.open(Paths.get("source.txt"), StandardOpenOption.READ);
             FileChannel destChannel = FileChannel.open(Paths.get("destination.txt"), StandardOpenOption.WRITE, StandardOpenOption.CREATE)) {

            // Using transferTo
            long size = sourceChannel.size();
            long position = 0;

            while (position < size) {
                position += sourceChannel.transferTo(position, size - position, destChannel);
            }

            // Alternatively, using transferFrom
            // destChannel.transferFrom(sourceChannel, 0, sourceChannel.size());
        }
    }
}

2.2. Merging Content from Multiple Files into One

In this example, we are reading the file content from 3 different files and writing their combined output into a fourth file.

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.nio.channels.FileChannel;
import java.nio.channels.WritableByteChannel;
 
public class ChannelTransferExample {

  public static void main(String[] argv) throws Exception {

    //Input files
    String[] inputFiles = new String[]{"inputFile1.txt","inputFile2.txt","inputFile3.txt"};
     
    //Files contents will be written in these files
    String outputFile = "outputFile.txt";
     
    //Get channel for output file
    FileOutputStream fos = new FileOutputStream(new File(outputFile));
    WritableByteChannel targetChannel = fos.getChannel();
     
    for (int i = 0; i < inputFiles.length; i++) {
    
      //Get channel for input files
      FileInputStream fis = new FileInputStream(inputFiles[i]);
      FileChannel inputChannel = fis.getChannel();
 
      //Transfer data from input channel to output channel
      inputChannel.transferTo(0, inputChannel.size(), targetChannel);
 
      //close the input channel
      inputChannel.close();
      fis.close();
    }
     
    //finally close the target channel
    targetChannel.close();
    fos.close();
  }
}

Drop your comments and suggestions in the comments section.

Happy Learning !!

Weekly Newsletter

Stay Up-to-Date with Our Weekly Updates. Right into Your Inbox.

Comments

Subscribe
Notify of
2 Comments
Most Voted
Newest Oldest
Inline Feedbacks
View all comments

About Us

HowToDoInJava provides tutorials and how-to guides on Java and related technologies.

It also shares the best practices, algorithms & solutions and frequently asked interview questions.