Come sapere se una copia di file è “in corso” / completa in java (1.6)

Sto scrivendo un’utilità di monitoraggio delle directory in java (1.6) usando il polling a determinati intervalli usando il valore long lastModified come indicazione del cambiamento. Ho scoperto che quando il mio intervallo di polling è piccolo (secondi) e il file copiato è grande, l’evento di modifica viene triggersto prima del completamento effettivo della copia dei file.

Vorrei sapere se esiste un modo per trovare lo stato del file come in transito, completo, ecc.

Ambienti: Java 1.6; dovrebbe lavorare su Windows e Linux.

Ci sono due approcci che ho usato in passato e che sono indipendenti dalla piattaforma.

1 / Questo era per i trasferimenti FTP dove ho controllato ciò che è stato inserito, quindi potrebbe non essere direttamente rilevante.

Fondamentalmente, qualunque cosa stia mettendo un file, file.txt , al termine, metterà anche un piccolo file fittizio (probabilmente zero byte) chiamato file.txt.marker (per esempio).

In questo modo, lo strumento di monitoraggio cerca solo il file marker e, quando lo fa, sa che il vero file è completo. Può quindi elaborare il file reale ed eliminare il marcatore.

2 / Una durata invariata.

Fare in modo che il programma di monitoraggio attenda fino a quando il file non viene modificato per N secondi (dove N è ragionevolmente garantito che sia sufficientemente grande da consentire il completamento del file).

Ad esempio, se la dimensione del file non è cambiata in 60 secondi, ci sono buone probabilità che sia finita.

C’è un atto di bilanciamento tra il non pensare che il file sia finito solo perché non c’è attività su di esso, e l’attesa una volta che è finita prima di poter iniziare l’elaborazione. Questo è meno un problema per la copia locale rispetto all’FTP.

Questa soluzione ha funzionato per me:

 File ff = new File(fileStr); if(ff.exists()) { for(int timeout = 100; timeout>0; timeout--) { RandomAccessFile ran = null; try { ran = new RandomAccessFile(ff, "rw"); break; // no errors, done waiting } catch (Exception ex) { System.out.println("timeout: " + timeout + ": " + ex.getMessage()); } finally { if(ran != null) try { ran.close(); } catch (IOException ex) { //do nothing } ran = null; } try { Thread.sleep(100); // wait a bit then try again } catch (InterruptedException ex) { //do nothing } } System.out.println("File lockable: " + fileStr + (ff.exists()?" exists":" deleted during process")); } else { System.out.println("File does not exist: " + fileStr); } 

Questa soluzione si basa sul fatto che non è ansible aprire il file per la scrittura se è aperto un altro processo. Rimarrà nel ciclo finché non viene raggiunto il valore di timeout o il file può essere aperto. I valori di timeout dovranno essere regolati in base alle reali esigenze dell’applicazione. Ho anche provato questo metodo con i canali e tryLock (), ma non sembrava necessario.

Intendi dire che stai aspettando l’ lastModified momento modificato per stabilirti? Nel migliore dei casi questo sarà un po ‘approssimativo.

Che ne dici di provare ad aprire il file con accesso in scrittura (accodando piuttosto che troncando il file, ovviamente)? Ciò non avrà successo se un altro processo sta ancora tentando di scrivere su di esso. È un po ‘brutto, in particolare perché è probabile che si tratti di utilizzare eccezioni per il controllo del stream (ick), ma penso che funzionerà.

Se ho capito bene la domanda, stai cercando un modo per distinguere se la copia di un file è completa o ancora in corso?

Che ne dici di confrontare le dimensioni del file di origine e di destinazione (es. File.length ())? Se sono uguali, la copia è completa. Altrimenti, è ancora in corso.

Non sono sicuro che sia efficiente dal momento che richiederebbe ancora il polling. Ma “potrebbe” funzionare.

È ansible esaminare il caricamento di file online con tecniche progressbar: utilizzano OutputStreamListener e il writer personalizzato per notificare all’ascoltatore i byte scritti.

http://www.missiondata.com/blog/java/28/file-upload-progress-with-ajax-and-java-and-prototype/

Caricamento file con Java (con barra di avanzamento)

Abbiamo usato per monitorare la modifica della dimensione del file per determinare se il file è in Completo o meno.

abbiamo usato l’integrazione di file Spring endpoint per eseguire il polling di una directory per ogni 200 ms.

Una volta che il file è stato rilevato (indipendentemente dal fatto che sia completo o meno), abbiamo un filtro File cliente, che avrà un metodo di interfaccia “accept (File file)” per restituire un flag che indica se possiamo elaborare il file.

Se il False viene restituito dal filtro, questa istanza FILE verrà ignorata e verrà prelevata durante il successivo polling per lo stesso processo di filtraggio.

Il filtro effettua le seguenti operazioni:

In primo luogo, otteniamo le dimensioni del file corrente. e aspetteremo per 200ms (può essere inferiore) e ricontrollare le dimensioni. Se la dimensione è diversa, riproveremo per 5 volte. Solo quando la dimensione del file smette di crescere, il file sarà contrassegnato come COMPLETATO (cioè restituisce true).

Il codice di esempio utilizzato è il seguente:

 public class InCompleteFileFilter extends AbstractFileListFilter { protected Object monitor = new Object(); @Override protected boolean accept(F file) { synchronized (monitor){ File currentFile = (File)file; if(!currentFile.getName().contains("Conv1")){return false;} long currentSize = currentFile.length(); try { Thread.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); } int retryCount = 0; while(retryCount++ < 4 && currentFile.length() > currentSize){ try { Thread.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); } } if(retryCount == 5){ return false; }else{ return true; } } } }