Ova

How to Copy a File in Java Code?

Published in Java File Copy 6 mins read

To copy a file in Java, the most recommended and modern approach is to use the java.nio.file.Files.copy() method, which provides efficient and robust file operations as part of the NIO.2 API introduced in Java 7.

1. Using java.nio.file.Files.copy() (Recommended)

The Files class, located in the java.nio.file package, provides several static methods for interacting with the file system. The copy() method is designed for straightforward and performant file duplication.

Key Features of Files.copy():

  • Path-based: It operates on Path objects, which are an improved way to represent file system paths compared to the older File class.
  • Flexibility with CopyOptions: You can customize the copy behavior using StandardCopyOption enum values.
  • Efficient: Handles buffering internally, making it generally more efficient than manual stream copying.
  • Error Handling: Throws IOException for file system errors, which should be handled.

The primary method signature for copying a file from one path to another is:
Path copy(Path source, Path target, CopyOption... options)

By default, the copy operation fails if the target file already exists, throwing a FileAlreadyExistsException. To overwrite an existing target file, you must specify the StandardCopyOption.REPLACE_EXISTING option.

Common StandardCopyOptions:

Option Description
REPLACE_EXISTING If the target file exists, it is replaced by the source file. If not specified, and the target file exists, the copy operation fails with a FileAlreadyExistsException.
COPY_ATTRIBUTES Attempts to copy the file attributes (e.g., last modified time, permissions) of the source file to the target file. The exact attributes copied depend on the file system.
NOFOLLOW_LINKS If the source file is a symbolic link, the link itself (not its target) is copied. If not specified, and the source is a symbolic link, the target of the link is copied.

Practical Examples:

To use Files.copy(), you'll typically need to import java.nio.file.Files, java.nio.file.Path, java.nio.file.Paths, and potentially java.nio.file.StandardCopyOption. Always wrap file operations in a try-catch block to handle potential IOExceptions.

a. Basic File Copy (Fails if Target Exists)

This example attempts to copy source.txt to target.txt. If target.txt already exists, a FileAlreadyExistsException will be thrown.

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.FileAlreadyExistsException;

public class FileCopyBasic {
    public static void main(String[] args) {
        Path sourcePath = Paths.get("data/source.txt"); // Replace with your source file path
        Path targetPath = Paths.get("data/target.txt"); // Replace with your target file path

        try {
            Files.copy(sourcePath, targetPath);
            System.out.println("File copied successfully to: " + targetPath);
        } catch (FileAlreadyExistsException e) {
            System.err.println("Error: Target file already exists at " + targetPath + ". Use REPLACE_EXISTING to overwrite.");
        } catch (IOException e) {
            System.err.println("Error copying file: " + e.getMessage());
            e.printStackTrace();
        }
    }
}

b. Copying and Overwriting an Existing File

To overwrite the target file if it already exists, use StandardCopyOption.REPLACE_EXISTING.

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;

public class FileCopyOverwrite {
    public static void main(String[] args) {
        Path sourcePath = Paths.get("data/source.txt");
        Path targetPath = Paths.get("data/existing_target.txt");

        try {
            Files.copy(sourcePath, targetPath, StandardCopyOption.REPLACE_EXISTING);
            System.out.println("File copied successfully (overwriting if target existed) to: " + targetPath);
        } catch (IOException e) {
            System.err.println("Error copying file with overwrite: " + e.getMessage());
            e.printStackTrace();
        }
    }
}

c. Copying with Attributes

You can also copy file attributes like the last modified time along with the content using StandardCopyOption.COPY_ATTRIBUTES.

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;

public class FileCopyWithAttributes {
    public static void main(String[] args) {
        Path sourcePath = Paths.get("data/source.txt");
        Path targetPath = Paths.get("data/target_with_attributes.txt");

        try {
            Files.copy(sourcePath, targetPath,
                       StandardCopyOption.REPLACE_EXISTING,
                       StandardCopyOption.COPY_ATTRIBUTES);
            System.out.println("File copied successfully with attributes to: " + targetPath);
        } catch (IOException e) {
            System.err.println("Error copying file with attributes: " + e.getMessage());
            e.printStackTrace();
        }
    }
}

Other Files.copy() Overloads:

The Files class also provides overloads for copying between streams and paths, which can be useful when you have data as an InputStream or need to write to an OutputStream.

  • long copy(InputStream in, Path target, CopyOption... options): Copies all bytes from an input stream to a file.
  • long copy(Path source, OutputStream out): Copies all bytes from a file to an output stream.

d. Copying from an InputStream to a Path

import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;

public class StreamToPathCopy {
    public static void main(String[] args) {
        Path targetPath = Paths.get("data/copied_from_stream.txt");
        // Simulate an InputStream, e.g., from a network connection, resource, or another file
        Path sourceFileForStream = Paths.get("data/stream_source.txt"); // Create this file for testing

        try (InputStream in = Files.newInputStream(sourceFileForStream)) {
            Files.copy(in, targetPath, StandardCopyOption.REPLACE_EXISTING);
            System.out.println("Content copied from InputStream to Path: " + targetPath);
        } catch (IOException e) {
            System.err.println("Error copying stream to file: " + e.getMessage());
            e.printStackTrace();
        }
    }
}

e. Copying from a Path to an OutputStream

import java.io.IOException;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption; // For creating/truncating OutputStream

public class PathToStreamCopy {
    public static void main(String[] args) {
        Path sourcePath = Paths.get("data/path_to_stream_source.txt"); // Create this file for testing
        Path targetFileForStream = Paths.get("data/copied_to_stream.txt");

        // Create an OutputStream that will write to targetFileForStream
        try (OutputStream out = Files.newOutputStream(targetFileForStream,
                                                     StandardOpenOption.CREATE,
                                                     StandardOpenOption.TRUNCATE_EXISTING)) {
            Files.copy(sourcePath, out);
            System.out.println("Content copied from Path to OutputStream: " + targetFileForStream);
        } catch (IOException e) {
            System.err.println("Error copying file to stream: " + e.getMessage());
            e.printStackTrace();
        }
    }
}

2. Legacy Approach (Less Recommended for New Code)

Before Java 7's NIO.2 API, file copying was typically done by reading from a FileInputStream and writing to a FileOutputStream byte by byte, or using a buffer. While still functional, this approach is more verbose, requires manual resource management, and is generally less efficient for large files unless optimized with appropriate buffer sizes.

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.File;

public class LegacyFileCopy {
    public static void main(String[] args) {
        File sourceFile = new File("data/old_source.txt"); // Replace with your source file
        File targetFile = new File("data/old_target.txt"); // Replace with your target file

        try (FileInputStream fis = new FileInputStream(sourceFile);
             FileOutputStream fos = new FileOutputStream(targetFile)) {

            byte[] buffer = new byte[1024]; // Buffer size for efficiency
            int length;
            while ((length = fis.read(buffer)) > 0) {
                fos.write(buffer, 0, length);
            }
            System.out.println("File copied successfully using legacy streams to: " + targetFile.getAbsolutePath());

        } catch (IOException e) {
            System.err.println("Error copying file using legacy streams: " + e.getMessage());
            e.printStackTrace();
        }
    }
}

For modern Java development, stick to the java.nio.file.Files.copy() methods as they are more robust, concise, and optimized.

[[Java File Operations]]