Open In App

How to Copy a File in Multiple Threads Using Java?

Copying files is a task, in programming that deals with file manipulation. Although Java offers tools, for file handling copying files can slow down our application’s performance. To optimize this process, we can take advantage of multithreading, which enables threads to work on various sections of the file.

Prerequisites:

Before diving into multithreaded file copying, ensure you have a solid understanding of the following:



Copying a file in Multiple threads using Java

Imagine a large file split into smaller chunks. By using multithreading, we can have several threads working simultaneously with each thread responsible, for reading a chunk of data, from the source file and writing it to the destination file. This parallel approach greatly cuts down on the time it takes to copy the file especially when dealing with files and high-speed disks.

Here’s a breakdown of the process:



Example:

In this example we will copy contents of a source file into a destination file.




import java.io.*;
import java.nio.file.Files;
import java.util.concurrent.CountDownLatch;
  
public class GFG {
  
    public static void main(String[] args) throws IOException, InterruptedException {
        String sourcePath = "source.txt"; // To copy the file
        String destinationPath = "destination.txt"; // The destination file
  
        // Calculate chunk size (adjust based on file size and available threads)
        int chunkSize = 1024 * 1024; // 1 MB chunks
  
        // Get file size
        long fileSize = Files.size(new File(sourcePath).toPath());
  
        // Calculate number of chunks
        int numChunks = (int) Math.ceil((double) fileSize / chunkSize);
  
        CountDownLatch latch = new CountDownLatch(numChunks);
  
        // Create and start threads
        for (int i = 0; i < numChunks; i++) 
        {
            long start = i * chunkSize;
            long end = Math.min((i + 1) * chunkSize, fileSize);
            Thread thread = new Thread(new CopyTask(sourcePath, destinationPath, start, end, latch));
            thread.start();
        }
  
        // await() for all threads to finish
        latch.await();
  
        System.out.println("File copied successfully!");
    }
      
    static class CopyTask implements Runnable {
  
        private String sourcePath;
        private String destinationPath;
        private long start;
        private long end;
        private CountDownLatch latch;
  
        public CopyTask(String sourcePath, String destinationPath, long start, long end, CountDownLatch latch) {
            this.sourcePath = sourcePath;
            this.destinationPath = destinationPath;
            this.start = start;
            this.end = end;
            this.latch = latch;
        }
  
        @Override
        public void run() {
            try (RandomAccessFile sourceFile = new RandomAccessFile(sourcePath, "r");
                 RandomAccessFile destinationFile = new RandomAccessFile(destinationPath, "rw")) {
                sourceFile.seek(start);
                destinationFile.seek(start);
  
                byte[] buffer = new byte[1024]; // Use chunkSize here
                int bytesRead;
                while ((bytesRead = sourceFile.read(buffer)) > 0) {
                    destinationFile.write(buffer, 0, bytesRead);
                }
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                latch.countDown();
            }
        }
    }
}

Output:

If everything was correct, then output will be:

File copied successfully!

Live Example:


Article Tags :