Hallo zusammen,
ich bin Oliver und ich habe folgende Problemstellung und möchte dies mit einer kleinen Konsolenanwendung lösen.
Ich muss eine Textdatei in SQL einlesen. Dazu muss ich einen bestimmten Ordner überwachen, ob eine neue Datei vorliegt. Ist das der Fall lass ich einen kleinen Batch laufen. Anschließend geschieht der SQL-Import und der Ordner soll weiter überwacht werden. Und genau da besteht mein Problem die erste Datei, die im Ordner ankommt, wird wie erwartet verarbeitet danach kommt aber eine Fehlermeldung, dass er die aufbereitete Quelldatei, die durch den Batch erzeugt wird, nicht findet. Es wird nicht auf die Überwachung des Ordners gewartet, der dann ein neues Ereignis auslöst.
Zur Veranschaulichung habe ich eine Kurzform der Konsolen Anwendung beigefügt. Da ich neu auf dem Gebiet der C Sharp Programmierung bin hoffe ich das mir Auf diesem Wege jemand helfen kann. Vielen Dank schon mal.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
namespace test5
{
class Program
{
static void Main(string[] args)
{
////FileSystemWatcher
FileSystemWatcher FSW;
Console.WriteLine("Hello World!");
Console.WriteLine("Ordner überwachen starten");
// Filesystemwatcher anlegen
FSW = new FileSystemWatcher();
// Pfad und Filter festlegen
FSW.Path = @"C:\sql";
FSW.Filter = "*.txt";
// Events definieren
FSW.Created += new FileSystemEventHandler(FSW_Created);
// Filesystemwatcher aktivieren
FSW.EnableRaisingEvents = true;
Console.WriteLine("Listening...");
Console.WriteLine("(Press any key to exit.)");
Console.ReadLine();
void FSW_Created(object sender, FileSystemEventArgs e)
{
Console.WriteLine(("Erstellt: " + e.Name));
Console.WriteLine();
Console.WriteLine();
//// Batch für Vorbereitung
string systemzeit = DateTime.Now.ToString("yyyyMMddHHmmssfff");
// Datei umbenen
string path3 = @"c:\sql\" + e.Name;
string path4 = @"c:\sql\artikel_neu.txt";
File.Move(path3, path4);
// Batch ausführen
//System.Diagnostics.Process.Start(@"C:\sql\replace.bat");
System.IO.File.Copy(path4, @"c:\sql\artikel_bearbeitet.txt"); // nur zur Veranschaulichung des Batches
System.IO.File.Delete(path4);
Console.WriteLine("Batch für die Vorebeitung wurde ausgeführt");
Console.WriteLine();
//// StreamReader
Console.WriteLine("SQL Import wurde ausgeführt");
Console.WriteLine();
//// Nachbereitung
// Datei verschieben
string path = @"c:\sql\artikel_bearbeitet.txt";
string path2 = @"c:\sqlarchiv\" + systemzeit + "_" + "artikel_bearbeitet.txt";
File.Move(path, path2);
Console.WriteLine("{0} wurde nach verschoben {1}.", path, path2);
Console.WriteLine("Batch für die Nachebeitung wurde ausgeführt");
Console.WriteLine();
}
}
}
}
Hi,
also der Quellcode hat einige grundlegende Fehler / unpassende Umsetzungen, zum Beispiel, dass die Event-Verarbeitung im identischen Thread läuft wie die Überwachung selbst.
die durch den Batch erzeugt wird, nicht findet
Dazu können wir wenig sagen ausser, dass Du eigentlich immer bei jedem Dateizugriff prüfen musst, ob eine Datei existiert oder nicht.
Das ist ein Grundlegender Faktor bei der Interaktion mit dem Dateisystem.
Wenn eine Datei nicht gefunden wird dann meistens, weil die Datei nicht existiert.
Wo die Datei wirklich liegt bzw wo gesucht wird, das kannst nur Du selbst prüfen, zB mit [Artikel] Debugger: Wie verwende ich den von Visual Studio?
Das Problem wird aber sein, dass Du einfach Deine Pfade auch völlig "falsch" zusammen baust.
Wenn Du in die Dokumentation von FileSystemEventArgs Klasse (System.IO) schaust, dann siehst Du, dass der vollständige Pfad im Event mitgegeben wird.
Es gibt also keine Notwendigkeit, dass Du im Event selbst nochmal den Quellpfad mit String-Operationen zusammen baust.
Ohnehin sollte man niemals Pfade von Hand zusammen bauen, sondern mit der Pfad Klasse.
Dann hast Du noch so unlogische und vermutlich fatalere Fehler wie
string path3 = @"c:\sql\" + e.Name;
string path4 = @"c:\sql\artikel_neu.txt";
File.Move(path3, path4);
Du nimmst die Quell-Datei im überwachten Ordner, erstellt eine neue Datei im überwachten Ordner mit einem fixen Name.
Wozu führt das: es wird ein neuer Event geworfen, mit der Ziel-Datei als Quell-Datei.
Das hat zur Folge, dass Du Dir eine Endlos-Event-Schleife gebaut hast, weil Du auf selbst erzeugtes Zeug hörst und Du Dir selbst den Prozess neu startest.
Wenn Du mal den Debugger anwirfst, dann solltest Du auch merken, dass hier was nicht stimmen kann.
Also: niemals im überwachten Folder Dateien erstellen, die dem Watch-Pattern entsprechen und Du Dir nen endless Loop baust.
Es wird nicht auf die Überwachung des Ordners gewartet, der dann ein neues Ereignis auslöst.
Das hast Du auch nirgends programmiert. Wenn Du das willst, dann musst Du das entsprechend auch im Code umsetzen 😉
Dann abschließend noch der Hinweis, dass man Zeiten in solch einem Fall besser als UTC speichert und nicht als Systemzeit.
Zeiten sollten Unique sein, was Systemzeiten/ lokalisierte Zeiten nicht sind. Daher sollten Zeiten in Dateien oder in Dateinamen, genauso wie in Datenbanken, sich immer nach UTC richten.
[FAQ] DateTime vs. DateTimeOffset und der Umgang mit Zeiten in .NET
- performance is a feature -
Microsoft MVP - @Website - @AzureStuttgart - github.com/BenjaminAbt - Sustainable Code