Domanda

Abbiamo diverse applicazioni .NET che monitorano una directory per nuovi file, utilizzando FileSystemWatcher.I file vengono copiati da un'altra posizione, caricati tramite FTP, ecc.Quando arrivano, i file vengono elaborati in un modo o nell'altro.Tuttavia, un problema per il quale non ho mai visto una risposta soddisfacente è:per file di grandi dimensioni, come si fa a sapere quando è ancora in corso la scrittura sui file monitorati?Ovviamente, dobbiamo attendere che i file siano completi e chiusi prima di iniziare l'elaborazione.Gli argomenti dell'evento negli eventi FileSystemWatcher non sembrano risolvere questo problema.

È stato utile?

Soluzione

Hai provato ad ottenere un blocco in scrittura sul file?Se viene scritto, dovrebbe fallire, e sai che dovresti lasciarlo stare per un po'...

Altri suggerimenti

Se hai il controllo del programma che scrive i file nella directory, puoi fare in modo che il programma scriva i file in una directory temporanea e quindi li sposti nella directory controllata.Lo spostamento dovrebbe essere un'operazione atomica, quindi l'osservatore non dovrebbe vedere il file finché non è completamente nella directory.

Se non hai il controllo di ciò che viene scritto nella directory controllata, puoi impostare un'ora nell'osservatore in cui il file viene considerato completo quando rimane della stessa dimensione per il tempo specificato.Se l'elaborazione immediata non è un problema, impostare questo timer su qualcosa di relativamente grande è un modo abbastanza sicuro per sapere se il file è completo o non lo sarà mai.

L'evento "Changed" su FileSystemWatcher non dovrebbe attivarsi finché il file non viene chiuso.Guarda il mio rispondere ad una domanda simile.Esiste la possibilità che il meccanismo di download FTP chiuda il file più volte durante il download quando arrivano nuovi dati, ma penso che sia un po' improbabile.

A meno che il contenuto di un file non possa essere verificato per il completamento (ha un formato verificabile o include un checksum del contenuto) solo il mittente può verificare che sia arrivato l'intero file.

In passato ho utilizzato un metodo di blocco per inviare file di grandi dimensioni tramite FTP.

Il file viene inviato con un'estensione alternativa e viene rinominato una volta che il mittente è soddisfatto che sia tutto lì.

A quanto sopra è ovviamente abbinato un processo che periodicamente riordina i vecchi file con estensione temporanea.

Un'alternativa è creare un file di lunghezza zero con lo stesso nome ma con un'estensione .lck aggiuntiva.Una volta caricato completamente il file reale, il file lck viene eliminato.Il processo ricevente ovviamente ignora i file che hanno il nome di un file di lock.

Senza un sistema come questo il destinatario non potrà mai essere sicuro che l'intero file sia arrivato.

Il controllo dei file che non sono stati modificati in x minuti è soggetto a tutti i tipi di problemi.

Il metodo seguente tenta di aprire un file con autorizzazioni di scrittura.Bloccherà l'esecuzione finché il file non sarà completamente scritto sul disco:

/// <summary>
/// Waits until a file can be opened with write permission
/// </summary>
public static void WaitReady(string fileName)
{
    while (true)
    {
        try
        {
            using (System.IO.Stream stream = System.IO.File.Open(fileName, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite))
            {
                if (stream != null)
                {
                    System.Diagnostics.Trace.WriteLine(string.Format("Output file {0} ready.", fileName));
                    break;
                }
            }
        }
        catch (FileNotFoundException ex)
        {
            System.Diagnostics.Trace.WriteLine(string.Format("Output file {0} not yet ready ({1})", fileName, ex.Message));
        }
        catch (IOException ex)
        {
            System.Diagnostics.Trace.WriteLine(string.Format("Output file {0} not yet ready ({1})", fileName, ex.Message));
        }
        catch (UnauthorizedAccessException ex)
        {
            System.Diagnostics.Trace.WriteLine(string.Format("Output file {0} not yet ready ({1})", fileName, ex.Message));
        }
        Thread.Sleep(500);
    }
}

(dalla mia risposta ad a domanda correlata)

Probabilmente dovrai utilizzare alcuni segnali fuori banda:chiedi al produttore di "file.ext" di scrivere un fittizio "file.ext.end".

+1 per utilizzare un segnalatore file.ext.end, se possibile, dove il contenuto di file.ext.end è un checksum per il file più grande.Questo non è tanto per la sicurezza quanto per assicurarsi che nulla venga confuso lungo il percorso.Se qualcuno può inserire il proprio file nel flusso di grandi dimensioni, può anche sostituire il checksum.

Un blocco in scrittura non aiuta se il caricamento del file non è riuscito a metà e il mittente non ha ancora provato a inviare nuovamente (e bloccare nuovamente) il file.

Il modo in cui controllo in Windows se un file è stato completamente caricato tramite ftp è provare a rinominarlo.Se la ridenominazione fallisce, il file non è completo.Non molto elegante, lo ammetto, ma funziona.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top