2009-02-04 12 views
8

Ho bisogno di creare un programma java che creerà thread per cercare un file in una cartella particolare (cartella di origine) e scegliere immediatamente il file per il lavoro di processo (convertirlo in formato di file csv) una volta trovato il file nel cartella di origine. Il problema che sto affrontando ora è che il file che arriva alla cartella sorgente è di grandi dimensioni (lo strumento FTP è usato per copiare file dalla cartella server alla cartella sorgente), il thread sta selezionando quel file immediatamente prima di copiarlo completamente nella cartella sorgente e lanciare un'eccezione. Come posso interrompere il thread finché il file non viene copiato completamente nella cartella di origine ?. Deve selezionare il file per l'elaborazione solo dopo che il file è stato copiato completamente nella cartella di origine.Come gestire i file incompleti? Ottenere l'eccezione

+0

È bello sapere, quale eccezione? –

risposta

1

Dando per scontato che non hanno alcun controllo sul processo FTP ...

lascia che sia così. Quando ottieni l'eccezione, prova ad elaborarla di nuovo la volta successiva. Ripeti finché il file non viene elaborato. È buono per mantenere alcuni attributi in caso di eccezione per controllarlo più tardi, come; nome, ultima modifica, dimensione.

Controllare l'eccezione esatta prima di decidere di elaborarlo in seguito, l'eccezione potrebbe verificarsi per qualche altro motivo.

2

Se si ha il controllo sul processo che esegue l'FTP, è possibile che sia possibile creare un "file di bandiera" nella directory di origine immediatamente dopo che il file ftp per il file grande è terminato.

Quindi il thread Java deve controllare la presenza di questo file di flag, se è presente, c'è un file pronto per essere elaborato nella directory di origine. Prima di elaborare il file grande, il thread dovrebbe rimuovere il file di flag.

Il file di bandiera può essere qualsiasi cosa (anche un file vuoto).

3

Si potrebbe provare cose diverse:

  • controllare ripetutamente la data dell'ultima modifica e la dimensione del file fino a quando non cambia più per un determinato periodo di tempo, poi elaborarlo. (Come sottolineato da qbeuek, questo non è né sicuro né deterministico.)
  • Solo file di processo con nomi che soddisfano determinati criteri (ad esempio * .dat). Modificare il processo di upload/download FTP per caricare/scaricare file con un nome diverso (ad esempio * .dat.temp) e rinominare i file una volta completati.
  • Scaricare i file in una posizione diversa e spostarli nella directory di elaborazione una volta completati.
  • Come ha detto l'aceto, se non funziona la prima volta, riprovare più tardi. :)
+0

Non so perché abbiamo downvotes, a volte. La gente inizia a sparare ovunque. 100 reputazione è troppo bassa per downvotare qualcuno. Deve essere più alto, può essere 1000 o 2000. –

+0

Beh, a volte io voto fino in fondo per bilanciare i downvotes, dando al votatario +8 punti che altrimenti non riceverebbero, quindi è qualcosa. In questo caso avrei comunque votato la tua risposta, dura. – itsadok

+0

ti ho votato perché il primo elemento nell'elenco dei tuoi suggerimenti non è sicuro né deterministico. – qbeuek

4

Il modo più sicuro è quello di scaricare il file in una posizione diversa e quindi spostarlo nella cartella di destinazione.

Un'altra variante menzionata da Bombe è quella di cambiare il nome del file in un'altra estensione dopo il download e cercare solo i file con tale estensione.

+0

+1 Questo non è il modo più sicuro, ma l'unico modo per farlo. Tutte le altre opzioni sprecano risorse o sono insicure :) –

4

Ho letto solo il file che non è in modalità di scrittura. Questo è più sicuro in quanto ciò significa che nessun altro processo sta scrivendo in questo file. È possibile verificare se il file non è in modalità di scrittura utilizzando il metodo canWrite della classe File.

Questa soluzione funziona bene per me poiché ho anche lo stesso identico scenario che stai affrontando.

0

Se il sistema operativo è Linux e il kernel> 2.6.13, è possibile utilizzare l'API di notifica eventi del file system denominata inotify. Qui c'è un'implementazione Java: https://bitbucket.org/nbargnesi/inotify-java.

Ecco un esempio di codice (fortemente ispirato al sito Web).

 try { 
     Inotify i = new Inotify(); 
     InotifyEventListener e = new InotifyEventListener() { 

      @Override 
      public void filesystemEventOccurred(InotifyEvent e) { 
       System.out.println("inotify event occurred!"); 
      } 

      @Override 
      public void queueFull(EventQueueFull e) { 
       System.out.println("inotify event queue: " + e.getSource() + 
         " is full!"); 
      } 

     }; 
     i.addInotifyEventListener(e); 
     i.addWatch(System.getProperty("user.home"), Constants.IN_CLOSE_WRITE); 
    } catch (UnsatisfiedLinkError e) { 
     System.err.println("unsatisfied link error"); 
    } catch (UserLimitException e) { 
     System.err.println("user limit exception"); 
    } catch (SystemLimitException e) { 
     System.err.println("system limit exception"); 
    } catch (InsufficientKernelMemoryException e) { 
     System.err.println("insufficient kernel memory exception"); 
    } 
0

Questo è in Grails e sto usando FileUtils libreria dal Apache Commons fama. La funzione sizeof restituisce la dimensione in byte.

def fileModified = sourceFile.lastModified() 
    def fileSize = FileUtils.sizeOf(sourceFile) 

    Thread.sleep(3000) //sleep to calculate size difference if the file is currently getting copied 

    if((fileSize != FileUtils.sizeOf(sourceFile)) && (fileModified != sourceFile.lastModified())) //the file is still getting copied to return 
    { 
     if(log.infoEnabled) 
      log.info("File is getting copied!") 
     return 
    } 

    Thread.sleep(1000) //breather for picking up file just copied. 

prega di notare che questo dipende anche da ciò che di utilità o sistema operativo utilizzato per trasferire i file. La scommessa più sicura è copiare il file che è stato copiato o è stato copiato in diversi file o directory. Il processo di copia è robusto e ti assicura che il file è presente dopo il processo di copia. Quello che sto usando è da API commons.

FileUtils.copyFileToDirectory (File f, directory D)

Se si sta copiando un file enorme che è in procinto di ottenere copiato attenzione che questo richiederà tempo e come si potrebbe iniziare questo in filo parallelo o meglio avere una singola applicazione dedicata per il processo di trasferimento.

Problemi correlati