Pergunta

Eu tenho um arquivo .csv que é atualizado com freqüência (cerca de 20 a 30 vezes por minuto). Eu quero inserir as linhas recém-adicionadas a um banco de dados assim que eles são escritos para o arquivo.

FileSystemWatcher classe escutas para o arquivo notificações de alteração do sistema e pode elevar um evento sempre que há uma mudança em um arquivo especificado. O problema é que o FileSystemWatcher não pode determinar exatamente quais linhas foram adicionadas ou removidas (tanto quanto eu sei).

Uma maneira de ler essas linhas é salvar e comparar a contagem de linhas entre as mudanças e ler a diferença entre o último e penúltimo mudança. No entanto, eu estou procurando um aspirador de solução (talvez mais elegante).

Foi útil?

Solução

Eu escrevi algo muito semelhante. Eu usei o FileSystemWatcher para receber notificações sobre alterações. Então, usei um FileStream para ler os dados (mantendo o controle de minha última posição dentro do arquivo e procurando que antes de ler os novos dados). Então eu adicionar os dados lidos para um buffer que extrai automaticamente linhas completas e, em seguida, saídas, em seguida, para a interface do usuário.

. Nota: "this.MoreData (..) é um evento, o ouvinte dos quais contribui para o tampão acima mencionado, e alças a extracção linha completa

Nota: Como já foi mencionado, isto só irá funcionar se as modificações são sempre adições ao arquivo. As eventuais supressões causará problemas.

Espero que isso ajude.

   public void File_Changed( object source, FileSystemEventArgs e )
    {
        lock ( this )
        {
            if ( !this.bPaused )
            {
                bool bMoreData = false;

                // Read from current seek position to end of file
                byte[] bytesRead = new byte[this.iMaxBytes];
                FileStream fs = new FileStream( this.strFilename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite );

                if ( 0 == this.iPreviousSeekPos )
                {
                    if ( this.bReadFromStart )
                    {
                        if ( null != this.BeginReadStart )
                        {
                            this.BeginReadStart( null, null );
                        }
                        this.bReadingFromStart = true;
                    }
                    else
                    {
                        if ( fs.Length > this.iMaxBytes )
                        {
                            this.iPreviousSeekPos = fs.Length - this.iMaxBytes;
                        }
                    }
                }

                this.iPreviousSeekPos = (int)fs.Seek( this.iPreviousSeekPos, SeekOrigin.Begin );
                int iNumBytes = fs.Read( bytesRead, 0, this.iMaxBytes );
                this.iPreviousSeekPos += iNumBytes;

                // If we haven't read all the data, then raise another event
                if ( this.iPreviousSeekPos < fs.Length )
                {
                    bMoreData = true;
                }

                fs.Close();

                string strData = this.encoding.GetString( bytesRead );
                this.MoreData( this, strData );

                if ( bMoreData )
                {
                    File_Changed( null, null );
                }
                else
                {
                    if ( this.bReadingFromStart )
                    {
                        this.bReadingFromStart = false;
                        if ( null != this.EndReadStart )
                        {
                            this.EndReadStart( null, null );
                        }
                    }
                }
            }
        }

Outras dicas

Right, o FileSystemWatcher não sabe nada sobre o conteúdo de seu arquivo. Vai dizer-lhe se ele mudou, etc., mas não o que mudou.

Você está adicionando apenas para o arquivo? Foi um pouco claro a partir do posto de saber se linhas foram adicionados ou também pode ser removido. Supondo que eles são anexados, a solução é bastante simples, caso contrário, você estará fazendo algumas comparações.

Eu acho que você deve usar NTFS Change Journal ou similar:

O diário de alteração é usado por NTFS para fornecer um log persistente de todas alterações feitas nos arquivos no volume. Para cada volume, o NTFS usa a mudança revista para rastrear informações sobre acrescentados, apagados e modificados arquivos . O diário de alteração é muito mais eficiente do que carimbos de tempo ou arquivo notificações para determinar mudanças em um determinado espaço de nomes.

Você pode encontrar uma href="http://www.microsoft.com/technet/prodtechnol/windows2000serv/reskit/core/fncc_fil_khzt.mspx?mfr=true" rel="nofollow descrição no TechNet . Você vai precisar usar PInvoke em .NET.

Gostaria de manter o texto atual na memória se ele é pequeno o suficiente e, em seguida, utilizar um algoritmo de comparação para verificar se o novo texto e texto anterior mudou. Esta biblioteca, http://www.mathertel.de/Diff/ , não só lhe dirá que alguma coisa mudou, mas o que mudou também. Então você pode inserir os dados alterados na base de dados.

fora do topo da minha cabeça, você pode armazenar o último tamanho do arquivo conhecido. Verifique contra o tamanho do arquivo, e quando ela muda, abra um leitor.

Em seguida, procure o leitor para o seu tamanho último arquivo, e começar a ler a partir daí.

Você está certo sobre o FileSystemWatcher. Você pode ouvir criados, apagados, etc. eventos modificados, mas você não conseguir mais profundo do que o arquivo que os criou.

Você tem controle sobre o próprio arquivo? Você poderia mudar o modelo ligeiramente para usar o arquivo como um buffer. Em vez de um arquivo, tenho dois. Uma delas é a encenação, uma é a soma de toda a saída processada. Leia todas as linhas do seu "tampão" arquivo, processá-los, em seguida, inseri-los no final do outro arquivo que é o total de todas as linhas de processados. Em seguida, exclua as linhas que você processados. Desta forma, todas as informações no seu arquivo está pendente de processamento. O problema é que se o sistema for diferente de gravação (ou seja, também exclui linhas), então ele não vai funcionar.

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