2012-02-18 17 views
24

Sto cercando di verificare se un certo file java.io.p è aperto da un programma esterno. Su Windows Io uso questo semplice trucco:Come verificare se un file è aperto da un altro processo (Java/Linux)?

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

So che i sistemi basati su UNIX consentono di aprire i file in più processi ... C'è un trucco simile per ottenere lo stesso risultato per i sistemi basati su UNIX?

Qualsiasi aiuto/modifico molto apprezzato :-)

+0

hai assolutamente ragione ... ma ho bisogno di questa funzionalità per monitorare lo stato del file (cosa che faccio con WatchServices in Java 7). ma devo anche rilevare quando un determinato file viene chiuso di nuovo per sbloccarlo, in modo che altri utenti possano modificarlo nuovamente. – salocinx

+0

Puoi chiamare a 'lsof'? – tchrist

+0

Questa è la prossima cosa che cercherò di fare. lsof sembra esistere su numerose distribuzioni Linux. L'apertura di un nuovo processo con lsof e la lettura dello standard output faranno il loro lavoro. Presenterò la mia soluzione domani in questo thread. grazie mille! – salocinx

risposta

0

Si può provare questo tipo di codice semaforo per un blocco di file da @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

molte grazie, ci provo! – salocinx

+0

my pleasure @NicolasBaumgardt :) –

+3

Questo funziona solo se tutti gli altri usano questo codice. Non realistico in meno. – tchrist

3

È possibile eseguire dal programma Java l'utilità lsof Unix ti dice quale processo sta usando un file, quindi analizza il suo output. Per eseguire un programma dal codice Java, utilizzare, ad esempio, le classi Runtime, Process, ProcessBuilder. Nota: il programma Java non sarà portatile, in questo caso, contraddicendo il concetto di portabilità, in modo da pensare due volte se si ha realmente bisogno di questo :)

+0

grazie mille per la tua soluzione. So che sto entrando in problemi di portabilità, ma le piattaforme di destinazione sono limitate a win/unix/mac. spero di trovare una strategia "solida" per ogni sistema operativo :-) – salocinx

+5

Il problema più grande non è la portabilità, ma anche se si usa lsof e si analizza il suo output e si vede che nessuno sta usando questo file, nulla garantisce che sul prossimo linea nel tuo codice qualcosa non ha aperto il file che ti interessa –

8

Ecco un esempio come utilizzare lsof per i sistemi basati su 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; 
} 

Spero che questo aiuti.

+0

non sembra funzionare su Android. –

1

Grazie per il suggerimento originale. Ho un piccolo aggiornamento che è un po 'importante che il metodo:

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: non funziona su Linux. Sarà comunque possibile aprire il file anche se è in uso. – mdewit

3

Questo dovrebbe funzionare anche per i sistemi Windows. Ma attenzione, non funziona per 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; 
    } 
Problemi correlati