2012-02-18 21 views
24

Estoy tratando de verificar si un determinado programa java.io.File está abierto. En las ventanas que utilizo este sencillo truco:¿Cómo comprobar si un archivo está abierto por otro proceso (Java/Linux)?

try { 
    FileOutputStream fos = new FileOutputStream(file); 
    // -> file was closed 
} catch(IOException e) { 
    // -> file still open 
} 

Sé que los sistemas basados ​​en UNIX permiten abrir archivos en múltiples procesos ... ¿Hay un truco similar para lograr el mismo resultado para los sistemas basados ​​en UNIX?

Cualquier ayuda/hack muy apreciada :-)

+0

tiene toda la razón ... pero necesito esta funcionalidad para controlar el estado del archivo (que hago con WatchServices en Java 7). pero también necesito detectar cuándo se cierra un archivo en particular nuevamente para desbloquearlo, para que otros usuarios puedan editarlo nuevamente. – salocinx

+0

¿Puedes llamar a 'lsof'? – tchrist

+0

Esto es lo siguiente que intentaré hacer. lsof parece existir en distribuciones Linux bastante numerosas. Abrir un nuevo proceso con lsof y leer el resultado estándar hará el trabajo. Presentaré mi solución mañana en este hilo. gracias hasta ahora! – salocinx

Respuesta

0

Puede probar este código de tipo semáforo para un bloqueo de archivo por @ZZ Coder

File file = new File(fileName); 
FileChannel channel = new RandomAccessFile(file, "rw").getChannel(); 

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(); 
} 
+1

muchas gracias, lo probaré! – salocinx

+0

my pleasure @NicolasBaumgardt :) –

+3

Eso solo funciona si todos los demás usan este código. No es realista en lo más mínimo. – tchrist

3

Puede ejecutar programa Java desde la utilidad de Unix que lsof te dice qué proceso está usando un archivo, luego analiza su resultado. Para ejecutar un programa desde código Java, use, por ejemplo, las clases Runtime, Process, ProcessBuilder. Nota: el programa Java no va a ser desmontables en este caso, lo que contradice el concepto de portabilidad, por lo que pensar dos veces si realmente necesita este :)

+0

muchas gracias por su solución. Sé que me estoy metiendo en problemas de portabilidad, pero las plataformas de destino están limitadas a win/unix/mac. Espero encontrar una estrategia "sólida" para cada sistema operativo :-) – salocinx

+5

El problema más grande no es la portabilidad, sino que incluso si usa lsof y analiza su salida y ve que nadie está utilizando este archivo, nada le garantiza que en el siguiente línea en su código algo no ha abierto el archivo que le interesa –

8

He aquí una muestra de cómo utilizar lsof para sistemas basados ​​en UNIX:

public static boolean isFileClosed(File file) { 
    try { 
     Process plsof = new ProcessBuilder(new String[]{"lsof", "|", "grep", file.getAbsolutePath()}).start(); 
     BufferedReader reader = new BufferedReader(new InputStreamReader(plsof.getInputStream())); 
     String line; 
     while((line=reader.readLine())!=null) { 
      if(line.contains(file.getAbsolutePath())) {        
       reader.close(); 
       plsof.destroy(); 
       return false; 
      } 
     } 
    } catch(Exception ex) { 
     // TODO: handle exception ... 
    } 
    reader.close(); 
    plsof.destroy(); 
    return true; 
} 

Espero que esto ayude.

+0

no parece funcionar en Android. –

1

Gracias por la sugerencia original. Tengo una pequeña actualización que es algo importante que el método:

FileOutputStream fos = null; 
try { 
    // Make sure that the output stream is in Append mode. Otherwise you will 
    // truncate your file, which probably isn't what you want to do :-) 
    fos = new FileOutputStream(file, true); 
    // -> file was closed 
} catch(IOException e) { 
    // -> file still open 
} finally { 
    if(fos != null) { 
    try { 
     fos.close(); 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } 
} 

Cheers, Gumbatron

+0

Nota: no funciona en Linux. Aún podrá abrir el archivo incluso si está en uso. – mdewit

3

Ésta debería funcionar también para los sistemas Windows. ¡Pero atención, no funciona para Linux!

 private boolean isFileClosed(File file) { 
      boolean closed; 
      Channel channel = null; 
      try { 
       channel = new RandomAccessFile(file, "rw").getChannel(); 
       closed = true; 
      } catch(Exception ex) { 
       closed = false; 
      } finally { 
       if(channel!=null) { 
        try { 
         channel.close(); 
        } catch (IOException ex) { 
         // exception handling 
        } 
       } 
      } 
      return closed; 
    } 
Cuestiones relacionadas