Frage

Ich habe eine CSV-Datei, die häufig aktualisiert wird (etwa 20 bis 30 mal pro Minute). Ich möchte so schnell die neu hinzugefügten Zeilen in eine Datenbank einfügen, wie sie in die Datei geschrieben werden.

Die Filesystemwatcher Klasse hört auf die Datei System Änderungsbenachrichtigungen und kann ein Ereignis auslösen, wenn es eine Änderung in einer bestimmten Datei. Das Problem ist, dass der Filesystemwatcher nicht genau bestimmen können, welche Zeilen hinzugefügt oder entfernt wurden (soweit ich weiß).

Eine Möglichkeit, diese Zeilen zu lesen ist zu speichern und die Zeilenzahl zwischen Änderungen zu vergleichen und die Differenz zwischen der letzten und vorletzten Änderung zu lesen. Aber ich bin auf der Suche für eine sauberere (vielleicht elegantere) Lösung.

War es hilfreich?

Lösung

Ich habe etwas sehr ähnlich geschrieben. Ich benutzen den Filesystemwatcher Benachrichtigungen über Änderungen zu erhalten. Ich habe dann einen Filestream die Daten zu lesen (Spur meiner letzten Position innerhalb der Datei zu speichern und zu suchen, dass, bevor die neuen Daten zu lesen). Dann habe ich die gelesenen Daten in einen Puffer hinzufügen, die automatisch komplette Linien extrahiert und dann gibt dann auf der Benutzeroberfläche.

Hinweis: „this.MoreData (..) ist ein Ereignis, der Zuhörer, von denen den oben genannten Puffer ergänzt und übernimmt die komplette Linie Extraktion

.

Hinweis: Wie bereits erwähnt, wird dies nur funktionieren, wenn die Änderungen immer Ergänzungen der Datei sind. Streichungen werden zu Problemen führen.

Hope, das hilft.

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

Andere Tipps

Richtig, der Filesystemwatcher weiß nichts über Ihren Dateiinhalt. Es wird Ihnen sagen, ob es geändert wird, etc., aber nicht das, was geändert.

Handelt es sich um nur in die Datei? Es war ein wenig unklar, von der Post, ob Zeilen hinzugefügt wurden oder auch entfernt werden können. Unter der Annahme, sie angehängt sind, ist die Lösung ziemlich einfach, sonst werden Sie einige Vergleiche tun.

Ich glaube, Sie NTFS Change Journal verwenden sollte oder ähnlich:

  

Das Änderungsjournal wird von NTFS verwendet   bietet ein beständiges Protokoll aller   Änderungen an Dateien auf dem Datenträger aus.   Für jedes Volumen, verwendet NTFS die Änderung   Journal Titelinformationen über   hinzugefügt, gelöscht und geänderte Dateien .   Das Änderungsjournal ist viel mehr   effizienter als Zeitstempel oder eine Datei   Meldungen zur Bestimmung Änderungen   in einem bestimmten Namensraum.

Sie können eine Beschreibung auf TechNet rel="nofollow . Sie müssen PInvoke in .NET verwenden.

würde ich den aktuellen Text in Erinnerung behalten, wenn es klein genug ist, und dann einen Diff-Algorithmus verwenden, um zu überprüfen, ob der neue Text und vorheriger Text geändert. Diese Bibliothek, http://www.mathertel.de/Diff/ , werden Sie nicht nur sagen, dass sich etwas verändert, aber was auch geändert. So können Sie fügen Sie dann die geänderten Daten in die db.

aus der Spitze von meinem Kopf, können Sie die letzte bekannte Dateigröße speichern. Überprüfen Sie gegen die Dateigröße und wenn sie sich ändert, öffnen Sie ein Leser.

Dann den Leser auf Ihre letzte Dateigröße suchen und starten von dort zu lesen.

Sie haben Recht über die Filesystemwatcher. Sie können erstellt, geändert, gelöscht, usw. Ereignisse hören, aber bekommt man nicht tiefer als die Datei, die sie angehoben.

Sie haben die Kontrolle über die Datei selbst? Sie könnten das Modell ändern leicht die Datei wie ein Puffer zu verwenden. Statt einer Datei, haben zwei. Eine davon ist die Inszenierung, ist die Summe aller verarbeiteten Ausgangs. Lesen Sie alle Zeilen aus dem „Puffer“ Datei, verarbeiten sie und setzen Sie sie in das Ende einer anderen Datei, die die Summe aller Linien verarbeitet ist. Dann löschen Sie die Zeilen, die Sie verarbeitet. Auf diese Weise alle Informationen in der Datei fehlen noch Verarbeitung. Der Haken ist, dass, wenn das System ist etwas anderes als schreiben (das heißt auch löscht Zeilen), dann wird es nicht funktionieren.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top