Pergunta

Temos vários .NET applications que o monitor de um diretório para novos arquivos, usando o FileSystemWatcher.Os arquivos são copiados a partir de outra localização, upload via FTP, etc.Quando eles chegam, os arquivos são processados de uma forma ou de outra.No entanto, um problema que eu nunca vi uma resposta satisfatória para é:para arquivos grandes, como é possível saber quando os arquivos estão sendo monitorados ainda a ser escrito?Obviamente, temos que esperar até que os arquivos estão completos e fechados antes de começar a processá-los.O evento args no FileSystemWatcher eventos não parece resolver esta questão.

Foi útil?

Solução

Você já tentou obter um bloqueio de gravação no arquivo?Se ele está sendo escrito, que deve falhar, e você sabe que deixá-lo sozinho para um pouco...

Outras dicas

Se você tem o controle sobre o programa que está gravando os arquivos para o diretório, você pode mandar o programa gravar os arquivos para um diretório temporário e, em seguida, movê-los para o visto de diretório.A movimentação deve ser uma operação atômica, de modo que o observador não deve ver o ficheiro até que ele esteja totalmente no diretório.

Se você não está no controle do que está a escrever para o visto de diretório, você pode definir um período em que o observador de onde o arquivo será considerada concluída quando ela se manteve o mesmo tamanho para o tempo determinado.Se o processamento imediato não é uma preocupação, a definição deste temporizador para algo relativamente grande, é um sistema bastante seguro, para saber que o arquivo está completo ou nunca será.

O "Alterado" evento do FileSystemWatcher deve não deve fogo até que o arquivo é fechado.Ver o meu resposta a uma pergunta semelhante.Há uma possibilidade de que o FTP mecanismo de transferência fecha o arquivo várias vezes durante o download, como novos dados, mas eu acho que é um pouco improvável.

A menos que o conteúdo de um arquivo pode ser verificado para a conclusão (tem um verificáveis ou de formato inclui uma soma de verificação do conteúdo), somente o remetente pode verificar se um arquivo inteiro já chegou.

Eu tenho usado um fecho método para o envio de grandes arquivos via FTP no passado.

O arquivo é enviado com uma alternativa de extensão e é renomeado uma vez que o remetente está feliz, ele é tudo que existe.

O acima é, obviamente, combinado com um processo que, periodicamente, arruma antigas de arquivos com a extensão temporária.

Uma alternativa é criar um comprimento zero ficheiro com o mesmo nome, mas com um adicional .lck extensão.Uma vez que o arquivo real é totalmente carregado lck arquivo é excluído.O processo de recebimento, obviamente, ignora os arquivos que têm o nome de um arquivo de bloqueio.

Sem um sistema como esse, o receptor pode nunca ter a certeza de que o arquivo inteiro já chegou.

A verificação de arquivos que não foram alterados em x minutos está propenso a todos os tipos de problemas.

O método a seguir tenta abrir um arquivo com permissões de escrita.Ele irá bloquear a execução até que um arquivo é completamente escrito para o 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);
    }
}

(de minha resposta a um perguntas relacionadas)

Provavelmente você tem que ir com alguns de faixa de sinalização:tem o produtor de "arquivo.ext" escrever um manequim de arquivo".ext.fim".

+1 para usar um arquivo.ext.final sinalizador, se possível, onde o conteúdo do arquivo.ext.final é um checksum para o arquivo maior.Isto não é para a segurança de forma tanto quanto ele é para se certificar de que não tem nada com erros ao longo do caminho.Se alguém pode inserir seu próprio arquivo para o grande fluxo eles podem substituir a soma de bem.

Um bloqueio de escrita não ajuda se o ficheiro não foi possível carregar a meio e o remetente não tentei reenviar (e relocking) o arquivo ainda.

A maneira que eu verifique no Windows, se um arquivo foi completamente carregado por ftp é tentar mudar o nome.Se mudar o nome falhar, o arquivo não está completo.Não muito elegante, eu admito, mas funciona.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top