Domanda

Ho un file .csv che viene aggiornato frequentemente (circa 20-30 volte al minuto).Voglio inserire le righe appena aggiunte in un database non appena vengono scritte nel file.

IL FileSystemWatcher ascolta le notifiche di modifica del file system e può generare un evento ogni volta che si verifica una modifica in un file specificato.Il problema è che FileSystemWatcher non può determinare esattamente quali righe sono state aggiunte o rimosse (per quanto ne so).

Un modo per leggere quelle righe è salvare e confrontare il conteggio delle righe tra le modifiche e leggere la differenza tra l'ultima e la penultima modifica.Tuttavia, sto cercando una soluzione più pulita (forse più elegante).

È stato utile?

Soluzione

Ho scritto qualcosa di molto simile.Ho utilizzato FileSystemWatcher per ricevere notifiche sulle modifiche.Ho quindi utilizzato un FileStream per leggere i dati (tenendo traccia della mia ultima posizione all'interno del file e cercandola prima di leggere i nuovi dati).Quindi aggiungo i dati letti a un buffer che estrae automaticamente le righe complete e quindi le invia all'interfaccia utente.

Nota:"this.MoreData(..) è un evento, il cui ascoltatore si aggiunge al suddetto buffer e gestisce l'estrazione completa della riga.

Nota:Come già accennato, ciò funzionerà solo se le modifiche sono sempre aggiunte al file.Eventuali eliminazioni causeranno problemi.

Spero che questo ti aiuti.

   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 );
                        }
                    }
                }
            }
        }

Altri suggerimenti

Esatto, FileSystemWatcher non sa nulla del contenuto del tuo file.Ti dirà se è cambiato, ecc.ma non cosa è cambiato.

Stai solo aggiungendo al file?Dal post non era chiaro se le righe fossero state aggiunte o potessero anche essere rimosse.Supponendo che vengano aggiunti, la soluzione è piuttosto semplice, altrimenti dovrai fare alcuni confronti.

Penso che dovresti usare NTFS Change Journal o simile:

Il diario delle modifiche viene utilizzato da NTFS per fornire un registro persistente di tutte le modifiche apportate ai file sul volume.Per ogni volume, NTFS utilizza il diario di cambiamento Tieni traccia delle informazioni sui file aggiunti, eliminati e modificati.Il diario delle modifiche è molto più efficiente dei timestamp o delle notifiche di file per determinare le modifiche in uno spazio dei nomi determinato.

Puoi trovare un descrizione su TechNet.Dovrai utilizzare PInvoke in .NET.

Manterrei il testo corrente in memoria se è abbastanza piccolo e quindi utilizzerei un algoritmo diff per verificare se il nuovo testo e il testo precedente sono cambiati.Questa biblioteca, http://www.mathertel.de/Diff/, non solo ti dirà che qualcosa è cambiato ma anche cosa è cambiato.Quindi puoi quindi inserire i dati modificati nel db.

in cima alla mia testa, potresti memorizzare l'ultima dimensione del file conosciuta.Controlla la dimensione del file e, quando cambia, apri un lettore.

Quindi cerca nel lettore l'ultima dimensione del file e inizia a leggere da lì.

Hai ragione riguardo a FileSystemWatcher.Puoi ascoltare i file creati, modificati, eliminati, ecc.eventi ma non vai più in profondità del file che li ha generati.

Hai il controllo sul file stesso?Potresti modificare leggermente il modello per utilizzare il file come un buffer.Invece di un file, averne due.Uno è la stadiazione, uno è la somma di tutti gli output elaborati.Leggi tutte le righe dal tuo file "buffer", elaborale, quindi inseriscile alla fine di un altro file che rappresenta il totale di tutte le righe elaborate.Quindi, elimina le righe elaborate.In questo modo, tutte le informazioni nel tuo file sono in attesa di elaborazione.Il problema è che se il sistema è diverso dalla scrittura (ad es.elimina anche le righe), quindi non funzionerà.

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