File.renameTo()
Parece que Java es problemático, especialmente en Windows. Como dice la documentación de la API ,
Muchos aspectos del comportamiento de este método dependen inherentemente de la plataforma: es posible que la operación de cambio de nombre no pueda mover un archivo de un sistema de archivos a otro, que no sea atómico y que no tenga éxito si un archivo con el nombre de ruta abstracto de destino ya existe. Siempre se debe verificar el valor de retorno para asegurarse de que la operación de cambio de nombre fue exitosa.
En mi caso, como parte de un procedimiento de actualización, necesito mover (renombrar) un directorio que puede contener gigabytes de datos (muchos subdirectorios y archivos de diferentes tamaños). El movimiento siempre se realiza dentro de la misma partición / unidad, por lo que no hay una necesidad real de mover físicamente todos los archivos en el disco.
No debería haber ningún archivo bloqueado en el contenido del directorio que se va a mover, pero aún así, con bastante frecuencia, renameTo () no hace su trabajo y devuelve falso. (Solo supongo que quizás algunos bloqueos de archivos caducan de forma algo arbitraria en Windows).
Actualmente tengo un método alternativo que usa copiar y eliminar, pero esto apesta porque puede llevar mucho tiempo, dependiendo del tamaño de la carpeta. También estoy considerando simplemente documentar el hecho de que el usuario puede mover la carpeta manualmente para evitar esperar horas, potencialmente. Pero el Camino Correcto obviamente sería algo automático y rápido.
Entonces, mi pregunta es, ¿conoce un enfoque alternativo y confiable para hacer un movimiento rápido / cambio de nombre con Java en Windows , ya sea con JDK simple o alguna biblioteca externa? O si conoce una manera fácil de detectar y liberar cualquier bloqueo de archivo para una carpeta determinada y todo su contenido (posiblemente miles de archivos individuales), también estaría bien.
Editar : En este caso particular, parece que nos salimos con la suya simplemente renameTo()
teniendo en cuenta algunas cosas más; ver esta respuesta .
Respuestas:
Consulte también el
Files.move()
método en JDK 7.Un ejemplo:
fuente
Por lo que vale, algunas nociones adicionales:
En Windows,
renameTo()
parece fallar si el directorio de destino existe, incluso si está vacío. Esto me sorprendió, ya que lo había probado en Linux, donde teníarenameTo()
éxito si el objetivo existía, siempre que estuviera vacío.(Obviamente, no debería haber asumido que este tipo de cosas funciona igual en todas las plataformas; esto es exactamente sobre lo que advierte el Javadoc).
Si sospecha que puede haber algunos bloqueos de archivos persistentes, esperar un poco antes de mover / cambiar el nombre puede ayudar. (En un punto de nuestro instalador / actualizador agregamos una acción de "suspensión" y una barra de progreso indeterminada durante unos 10 segundos, porque podría haber un servicio colgando de algunos archivos). Quizás incluso haga un mecanismo de reintento simple que lo intente
renameTo()
y luego espere un período (que tal vez aumente gradualmente), hasta que la operación sea exitosa o se alcance algún tiempo de espera.En mi caso, la mayoría de los problemas parecen haberse resuelto teniendo en cuenta ambos aspectos anteriores, por lo que, después de todo, no necesitaremos hacer una llamada nativa al kernel o algo por el estilo.
fuente
La publicación original solicitaba "un enfoque alternativo y confiable para hacer un movimiento rápido / cambio de nombre con Java en Windows, ya sea con JDK simple o alguna biblioteca externa".
Otra opción que aún no se menciona aquí es la v1.3.2 o posterior de la biblioteca apache.commons.io , que incluye FileUtils.moveFile () .
Lanza una IOException en lugar de devolver un booleano falso en caso de error.
Vea también la respuesta de big lep en este otro hilo .
fuente
java.nio.file.Path.moveTo()
En mi caso, parecía ser un objeto muerto dentro de mi propia aplicación, que mantenía un identificador para ese archivo. Entonces esa solución funcionó para mí:
Ventaja: es bastante rápido, ya que no hay Thread.sleep () con un tiempo codificado específico.
Desventaja: ese límite de 20 es un número codificado. En todas mis pruebas, i = 1 es suficiente. Pero para estar seguro lo dejé a las 20.
fuente
Sé que esto parece un poco complicado, pero para lo que lo he estado necesitando, parece que los lectores y escritores almacenados en búfer no tienen problemas para crear los archivos.
Funciona bien para archivos de texto pequeños como parte de un analizador, solo asegúrese de que oldName y newName sean rutas completas a las ubicaciones de los archivos.
Saludos Kactus
fuente
El siguiente fragmento de código NO es una 'alternativa' pero me ha funcionado de manera confiable tanto en entornos Windows como Linux:
fuente
En Windows, uso
Runtime.getRuntime().exec("cmd \\c ")
y luego uso la función de cambio de nombre de la línea de comandos para cambiar el nombre de los archivos. Es mucho más flexible, por ejemplo, si desea cambiar el nombre de la extensión de todos los archivos txt en un directorio a bak, simplemente escriba esto en el flujo de salida:renombrar * .txt * .bak
Sé que no es una buena solución, pero aparentemente siempre me ha funcionado, mucho mejor que el soporte en línea de Java.
fuente
Por qué no....
funciona en nwindows 7, no hace nada si existingFile no existe, pero obviamente podría estar mejor instrumentado para solucionar esto.
fuente
Tuve un problema similar. El archivo se copió en lugar de moverse en Windows, pero funcionó bien en Linux. Solucioné el problema cerrando el fileInputStream abierto antes de llamar a renameTo (). Probado en Windows XP.
fuente
En mi caso, el error estaba en la ruta del directorio principal. Tal vez un error, tuve que usar la subcadena para obtener una ruta correcta.
fuente
Sé que apesta, pero una alternativa es crear un script bat que genere algo simple como "SUCCESS" o "ERROR", invocarlo, esperar a que se ejecute y luego verificar sus resultados.
Runtime.getRuntime (). Exec ("cmd / c start test.bat");
Este hilo puede resultar interesante. Consulte también la clase Process sobre cómo leer la salida de la consola de un proceso diferente.
fuente
Puede intentar robocopy . Esto no es exactamente un "cambio de nombre", pero es muy confiable.
fuente
Para mover / cambiar el nombre de un archivo, puede utilizar esta función:
Está definido en kernel32.dll.
fuente
Lo anterior es el código simple. He probado en Windows 7 y funciona perfectamente bien.
fuente