Java – Copiar archivos

Copiar un archivo son dos líneas, no las treinta del ejemplo con InputStream y OutputStream que se escribía antes de Java 7.

Copiar

import java.nio.file.*;

void main() throws Exception {
    Path origen  = Path.of("salida", "notas.txt");
    Path destino = Path.of("salida", "copia.txt");

    Files.copy(origen, destino, StandardCopyOption.REPLACE_EXISTING);
    IO.println("copiado, " + Files.size(destino) + " bytes");
}
salidacopiado, 6 bytes

Sin REPLACE_EXISTING no sobrescribe

Files.copy(origen, destino);     // el destino ya existe
salidaException in thread "main" java.nio.file.FileAlreadyExistsException: salida/copia.txt
	at java.base/sun.nio.fs.UnixFileSystem.copy(UnixFileSystem.java:989)

Es a propósito: la copia no pisa nada por accidente. Si quieres sobrescribir, hay que pedirlo. Las otras opciones útiles son COPY_ATTRIBUTES, que conserva fechas y permisos, y NOFOLLOW_LINKS, que copia el enlace simbólico en vez de su destino.

Desde un flujo, o hacia un flujo

try (var in = url.openStream()) {
    Files.copy(in, Path.of("descarga.bin"), StandardCopyOption.REPLACE_EXISTING);
}

Files.copy(Path.of("informe.pdf"), respuesta.getOutputStream());

El mismo método vale para guardar lo que llega por la red y para volcar un archivo a la respuesta de un servidor. Es el sustituto directo del bucle de read y write con un byte[1024] que había que escribir a mano.

Copiar una carpeta entera

Files.copy sobre una carpeta copia solo la carpeta, vacía. Para copiar el contenido hay que recorrerlo:

try (var rutas = Files.walk(origen)) {
    rutas.forEach(p -> {
        try {
            Files.copy(p, destino.resolve(origen.relativize(p)),
                       StandardCopyOption.REPLACE_EXISTING);
        } catch (IOException e) {
            throw new UncheckedIOException(e);
        }
    });
}

relativize saca la parte de la ruta que cuelga del origen y resolve la pega bajo el destino; así se reconstruye el árbol. Si esto lo vas a hacer a menudo, el FileUtils.copyDirectory de Apache Commons IO es una sola llamada.

Para…Usa
Copiar un archivoFiles.copy(origen, destino)
Sobrescribir si existeañade StandardCopyOption.REPLACE_EXISTING
Conservar fechas y permisosañade COPY_ATTRIBUTES
Guardar lo que llega por la redFiles.copy(flujo, destino)
Copiar una carpeta con todoFiles.walk + relativize

Más información en inglés: Copy files in Java.

Todo el código se compiló y se ejecutó con Java 25 LTS en un contenedor limpio antes de publicar esta página; las salidas están copiadas de esa ejecución.