Necesito escribir un renombrador de archivo por lotes personalizado. Tengo la mayor parte de esto hecho, excepto que no puedo averiguar cómo verificar si un archivo ya está abierto. Solo estoy usando el paquete java.io.File
y hay un método canWrite()
, pero eso no parece probar si el archivo está siendo utilizado por otro programa. ¿Alguna idea sobre cómo puedo hacer que esto funcione?Compruebe si el archivo ya está abierto
Respuesta
No creo que alguna vez consigas una solución definitiva para esto, el sistema operativo no necesariamente te dirá si el archivo está abierto o no.
Es posible que obtenga un poco de kilometraje de java.nio.channels.FileLock
, aunque el javadoc está cargado de advertencias.
Sí, no hay garantía de que el sistema operativo subyacente, o incluso el sistema de archivos, admita bloqueos de archivos de forma razonable. – aperkins
Su mejor opción es establecer un bloqueo exclusivo en el archivo. Si el archivo está abierto por otros procesos, obtendrá una excepción. Por ejemplo,
File file = new File(fileName);
FileChannel channel = new RandomAccessFile(file, "rw").getChannel();
// Get an exclusive lock on the whole file
FileLock lock = channel.lock();
try {
lock = channel.tryLock();
// Ok. You get the lock
} catch (OverlappingFileLockException e) {
// File is open by someone else
} finally {
lock.release();
}
Es una buena idea a primera vista, pero: acabo de ejecutar este código modificado con tres archivos diferentes: un archivo de Word, un archivo de Excel y un archivo de texto abierto con UltraEdit. Solo el archivo de texto causa OverlappingFileLockException. Los primeros dos causaron una excepción FileNotFoundException en RandomAccessFile.open(). Tendría que mirar getMessage() para determinar que la causa es que el archivo está bloqueado, lo cual es malo. Muy malo si tenemos en cuenta que el mensaje está localizado en el SO (está en alemán en mi máquina). –
Puede usar file.exists() para evitar bloquear recursos inexistentes. Y parece que solo necesitas uno: lock() o tryLock(). –
Estoy de acuerdo con serge_bg: doing tryLock() después de que lock() arroje una excepción OverlappingFileLockException. Además, el lock.release() debería ser un nivel más alto. Finalmente, ¿no es necesario que el canal también esté cerrado? –
(El Q & A es acerca de cómo lidiar con las cerraduras de Windows "abrir archivo" ... no cómo implementar este tipo de bloqueo de forma portátil.)
Todo este asunto está cargado de problemas de portabilidad y condiciones de carrera:
- Puede intentar usar FileLock, pero no es necesariamente compatible con su sistema operativo y/o sistema de archivos.
- Parece que en Windows es posible que no pueda usar FileLock si otra aplicación ha abierto el archivo de una manera particular.
- Incluso si logró usar FileLock o alguna otra cosa, todavía tiene el problema de que algo puede entrar y abrir el archivo entre la prueba del archivo y el cambio de nombre.
Una solución más simple y (probablemente) más robusta es intentar el cambio de nombre (o lo que sea que esté intentando hacer) y diagnosticar el valor de retorno y/o cualquier excepción de Java que surja debido a archivos abiertos.
Notas:
si utiliza la API
Files
lugar de la APIFile
obtendrá más información en el caso de un fallo.En los sistemas donde se le permite cambiar el nombre (o lo que sea) de un archivo bloqueado o abierto, no obtendrá ningún resultado de falla o excepciones. La operación solo tendrá éxito.
Podría estar equivocado, pero creo que en algunos sistemas de archivos (no tan exóticos) incluso puede mover el archivo mientras se escribe en él. –
@ JaroslavZáruba - ¿Cómo se relaciona eso con la pregunta? o mi respuesta? –
"intente cambiar el nombre ... y diagnosticar cualquier excepción de Java" - esto está lejos de ser robusto, en Linux FS típico no obtendrá ninguna exc eption –
El uso de la biblioteca Apache Commons IO ...
boolean isFileUnlocked = false;
try {
org.apache.commons.io.FileUtils.touch(yourFile);
isFileUnlocked = true;
} catch (IOException e) {
isFileUnlocked = false;
}
if(isFileUnlocked){
// Do stuff you need to do with a file that is NOT locked.
} else {
// Do stuff you need to do with a file that IS locked
}
// TO CHECK WHETHER A FILE IS OPENED
// OR NOT (not for .txt files)
// the file we want to check
String fileName = "C:\\Text.xlsx";
File file = new File(fileName);
// try to rename the file with the same name
File sameFileName = new File(fileName);
if(file.renameTo(sameFileName)){
// if the file is renamed
System.out.println("file is closed");
}else{
// if the file didnt accept the renaming operation
System.out.println("file is opened");
}
¡Simplemente genio! +1. –
No funcionará para Linux. En los sistemas de archivos POSIX, el nombre del archivo no es la clave principal, sino un enlace al contenido del archivo. Por lo tanto, puede cambiar el nombre o eliminar el archivo abierto. Nadie obtiene ningún error. –
Puede confirmar esto funciona para Windows10. Parece mucho más elegante que provocar una excepción. No funciona en Linux con ext4. – JosefScript
Si el archivo está en uso FileOutputStream fileOutputStream = new FileOutputStream(file);
vuelve java.io.FileNotFoundException con 'El proceso no tiene acceso al archivo porque está siendo utilizado por otro proceso 'en el mensaje de excepción.
Agradecería los comentarios sobre los motivos de los votos a la baja – Aikerima
Sobrescribió el contenido del archivo con cero bytes si el archivo no estaba en uso, por lo que básicamente eliminó el archivo. Se aplica a Linux (ext4) y Win10. El tercer vástago fue mío. – JosefScript
Tengo esta excepción cuando uso _FileOutputStream fileOutputStream = new FileOutputStream (archivo) _ –
En Windows he encontrado la respuesta https://stackoverflow.com/a/13706972/3014879 usando
fileIsLocked = !file.renameTo(file)
más útil, ya que evita los falsos positivos al procesar archivos protegido contra escritura.
org.apache.commons.io.FileUtils.touch(yourFile)
no comprueba si su archivo está abierto o no. En cambio, cambia la marca de tiempo del archivo a la hora actual.
que utilizan IOException y funciona muy bien:
try
{
String filePath = "C:\sheet.xlsx";
FileWriter fw = new FileWriter(filePath);
}
catch (IOException e)
{
System.out.println("File is open");
}
El uso de excepciones para el flujo de control normal se considera una práctica deficiente. Además, puede terminar dejando abierto 'fw' en el caso que no genere una excepción. –
para que pueda usar finalmente para que el archivo se cierre de todas formas FileWriter fw; try { String filePath = "C: \ sheet.xlsx"; fw = new FileWriter (filePath); } catch (IOException e) { System.out.println ("El archivo está abierto"); } finalmente { fw.close(); } – Ali
- 1. Compruebe si un archivo está abierto
- 2. compruebe si un archivo está abierto en Python
- 3. Compruebe si un puerto está abierto
- 4. C# compruebe si un puerto COM (en serie) ya está abierto
- 5. Determinar si un archivo está abierto
- 6. NSMutableArray compruebe si el objeto ya existe
- 7. compruebe si la variable de entorno ya está configurada
- 8. Ruby: compruebe si hay un puerto abierto
- 9. Python PySerial.¿Cómo saber si un puerto ya está abierto?
- 10. Excepción al abrir un archivo que ya está abierto
- 11. Delphi: compruebe si el archivo está en uso
- 12. compruebe si el archivo de entrada archivado está vacío jquery
- 13. Detectando si el diálogo de entrada de archivo está abierto
- 14. ¿Cómo verificar si un archivo ya está abierto por otro proceso en C?
- 15. compruebe si NSNumber está vacío
- 16. Compruebe si el archivo existe en ksh
- 17. Compruebe si "exec" está deshabilitado
- 18. Compruebe si un archivo está bloqueado en Java
- 19. Python: compruebe si un archivo está vacío o no
- 20. SQLAlchemy: compruebe si el objeto ya está presente en la tabla
- 21. C compruebe si el archivo existe
- 22. compruebe si el archivo existe en php
- 23. Compruebe si la cadena está vacía
- 24. ¿Cómo comprobar si un formulario de Windows ya está abierto y cerrarlo si es así?
- 25. Verificar si datepicker está abierto
- 26. Compruebe si se ha eliminado un archivo abierto después de abrirlo en python
- 27. cómo saltar a la pestaña si tratara de abrir el archivo ya abierto en Vim
- 28. ¿Cómo verifica si un archivo está abierto usando Perl?
- 29. Compruebe si el servidor SQL (cualquier versión) está instalado?
- 30. Django: compruebe si ya existe un objeto antes de agregar
Esta es dependiente de la plataforma. ¿Para qué plataforma es esto? – skaffman
Windows 2003 Server –
Acabo de repetir su pregunta porque podría tener que hacer eso llamando a WinAPI usando JNI o JNA. –