2008-11-18 143 views

Respuesta

71

Así es como hacer esto con java.nio operaciones:

public static void copyFile(File sourceFile, File destFile) throws IOException { 
    if(!destFile.exists()) { 
     destFile.createNewFile(); 
    } 

    FileChannel source = null; 
    FileChannel destination = null; 
    try { 
     source = new FileInputStream(sourceFile).getChannel(); 
     destination = new FileOutputStream(destFile).getChannel(); 

     // previous code: destination.transferFrom(source, 0, source.size()); 
     // to avoid infinite loops, should be: 
     long count = 0; 
     long size = source.size();    
     while((count += destination.transferFrom(source, count, size-count))<size); 
    } 
    finally { 
     if(source != null) { 
      source.close(); 
     } 
     if(destination != null) { 
      destination.close(); 
     } 
    } 
} 
+5

si existe el archivo ¿se agregará o sobrescribirá el contenido? – Janusz

+0

@Rigo Esto mueve solo archivos, no puedo mover directorios – Arasu

+11

Vale la pena señalar que Java 7 tiene [métodos de copiar/mover] más simples (http://docs.oracle.com/javase/tutorial/essential/io/ copy.html). – Tharwen

40

Aún no, pero el New NIO (JSR 203) tendrá soporte para estas operaciones comunes.

Mientras tanto, hay algunas cosas que se deben tener en cuenta.

File.renameTo generalmente funciona solo en el mismo volumen del sistema de archivos. Pienso en esto como el equivalente a un comando "mv". Úselo si puede, pero para soporte general de copia y movimiento, necesitará un respaldo.

Cuando un cambio de nombre no funciona, deberá copiar el archivo (eliminando el original con File.delete si se trata de una operación de "movimiento"). Para hacer esto con la mayor eficiencia, use los métodos FileChannel.transferTo o FileChannel.transferFrom. La implementación es específica de la plataforma, pero en general, al copiar de un archivo a otro, las implementaciones evitan el transporte de datos entre el kernel y el espacio del usuario, lo que genera un gran impulso en la eficiencia.

17

Salida: http://commons.apache.org/io/

Se tiene copia, y como se dijo el JDK ya tiene moverse.

No implemente su propio método de copia. Hay tantos flotando por ahí ...

+0

Commons IO tiene limitaciones con respecto al tamaño de los archivos que puede copiar. Para una solución de propósito general, se esperaría una implementación más sólida. – erickson

+3

La implementación de un método de copia propio es trivial y significa que no dependerá de una biblioteca completa. * Do * implementa tu propio –

+17

El método de copia está lejos de ser trivial. Puede hacer fácilmente uno correcto que no funciona con Streams, y uno rápido pero incorrecto con NIO. Nunca implemente sus propias utilidades cuando haya bibliotecas de calidad. – Pyrolistical

10

respuestas anteriores parecen estar desactualizado

Java File.renameTo() es probablemente la solución más fácil para API 7, y parece funcionar bien. Tenga cuidado ¡NO LANZA EXCEPCIONES, pero devuelve verdadero/falso!

Tenga en cuenta que parece haber problemas con él en versiones anteriores (igual que NIO).

Si necesita utilizar una versión anterior, marque here.

Here's an example for API7: 
     File f1= new File("C:\\Users\\.....\\foo"); 
     File f2= new File("C:\\Users\\......\\foo.old"); 
     System.err.println("Result of move:"+f1.renameTo(f2)); 

alternativa:

System.err.println("Move:" +f1.toURI() +"--->>>>"+f2.toURI()); 
    Path b1=Files.move(f1.toPath(), f2.toPath(), StandardCopyOption.ATOMIC_MOVE ,StandardCopyOption.REPLACE_EXISTING);); 
    System.err.println("Move: RETURNS:"+b1); 
+3

Si obtiene "El proceso no puede acceder al archivo porque lo está utilizando otro proceso". El proceso no puede acceder al archivo porque lo está utilizando otro proceso. "Excepción en el segundo fragmento de código, recuerde cerrar el archivo antes de moverlo ..... – ntg

+2

Hay otras situaciones inesperadas en las que falla, por ejemplo, en Linux si tiene dos sistemas de archivos diferentes montados en/mnt/a/mnt/b, no puede cambiar el nombre de un archivo/mnt/a/file1 a/mnt/b/file2, ya que en realidad es una operación de movimiento, File.renameTo fallará en este caso. – xask

+1

Esta es la mejor solución. Simplemente use Files.move() si le preocupa que la operación de cambio de nombre falle. – xtian

7

Intente utilizar org.apache.commons.io.FileUtils (utilidades de manipulación de archivos generales). Se proporcionan en los siguientes métodos:

(1) FileUtils.moveDirectory(File srcDir, File destDir) => Mueve un directorio .

(2) FileUtils.moveDirectoryToDirectory(File src, File destDir, boolean createDestDir) => Mueve un directorio a otro directorio.

(3) FileUtils.moveFile(File srcFile, File destFile) => Mueve un archivo.

(4) FileUtils.moveFileToDirectory(File srcFile, File destDir, boolean createDestDir) => Mueve un archivo a un directorio.

(5) FileUtils.moveToDirectory(File src, File destDir, boolean createDestDir) => Mueve un archivo o directorio al directorio de destino .

Es simple, fácil y rápido.

+0

¿Son estas funciones atómicas? – Sumit

0

Observación de interés: Intenté copiar el mismo archivo a través de varias clases de Java y el tiempo impreso en nano segundos.

Duración corriente con el byte FileOutputStream: 4 965 078

Duración utilizando BufferedOutputStream: 1 237 206

Duración utilizando (carácter de texto Lector: 2 858 875

Duración utilizando BufferedReader (secuencia de texto de carácter Buffered : 1 998 005

Duración usando (copiar archivos NIO): 18 351 115

w ¡Al usar la opción de copia de Archivos Nio, tomó casi 18 veces más! Nio es la opción más lenta para copiar archivos y BufferedOutputStream se ve como el más rápido. Usé el mismo archivo de texto simple para cada clase.

Cuestiones relacionadas