2010-03-03 4 views
9

In Linux wird viel IPC durchgeführt, indem an eine Datei in einem Prozess angefügt wird und der neue Inhalt von einem anderen Prozess gelesen wird.Das Lesen von Dateiinhalten ändert sich in. NET

Ich möchte das oben in Windows/.NET (zu chaotisch, um normale IPC wie Rohre verwenden) tun. Ich hänge an eine Datei aus einem Python-Prozess an, und ich möchte die Änderungen und NUR die Änderungen jedes Mal lesen, wenn FileSystemWatcher ein Ereignis meldet. Ich möchte nicht den gesamten Dateiinhalt im Speicher jedes Mal lesen, wenn ich nach Änderungen suche (die Datei wird riesig sein)

Jede Append-Operation hängt eine Reihe von Daten, die mit einem eindeutigen inkrementierenden Zähler (Zeitstempel + Schlüssel) und endet mit einem Zeilenumbruch.

Antwort

25
using (FileStream fs = new FileStream 
     (fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) 
    { 
     using (StreamReader sr = new StreamReader(fs)) 
     { 
      while (someCondition) 
      { 
       while (!sr.EndOfStream) 
        ProcessLinr(sr.ReadLine()); 
       while (sr.EndOfStream) 
        Thread.Sleep(100); 
       ProcessLinr(sr.ReadLine());    
      } 
     } 
    } 

dies wird Ihnen nur beigefügten Linien

+0

getestet, es funktioniert. Ziemlich coole Technik. –

+0

Eine großartige Lösung, kurz und tödlich! – MaYaN

9

Sie speichern die kann der letzten Leseoperation versetzt lesen helfen und um die Datei suchen, dass Offset, wenn Sie eine geänderte Datei Benachrichtigung. Es folgt ein Beispiel:

Main-Methode:

public static void Main(string[] args) 
{ 
    File.WriteAllLines("test.txt", new string[] { }); 

    new Thread(() => ReadFromFile()).Start(); 

    WriteToFile(); 
} 

Lesen von Datei-Methode:

private static void ReadFromFile() 
{ 
    long offset = 0; 

    FileSystemWatcher fsw = new FileSystemWatcher 
    { 
     Path = Environment.CurrentDirectory, 
     Filter = "test.txt" 
    }; 

    FileStream file = File.Open(
     "test.txt", 
     FileMode.Open, 
     FileAccess.Read, 
     FileShare.Write); 

    StreamReader reader = new StreamReader(file); 
    while (true) 
    { 
     fsw.WaitForChanged(WatcherChangeTypes.Changed); 

     file.Seek(offset, SeekOrigin.Begin); 
     if (!reader.EndOfStream) 
     { 
      do 
      { 
       Console.WriteLine(reader.ReadLine()); 
      } while (!reader.EndOfStream); 

      offset = file.Position; 
     } 
    } 
} 

Write-Methode in Datei:

private static void WriteToFile() 
{ 
    for (int i = 0; i < 100; i++) 
    { 
     FileStream writeFile = File.Open(
      "test.txt", 
      FileMode.Append, 
      FileAccess.Write, 
      FileShare.Read); 

     using (FileStream file = writeFile) 
     { 
      using (StreamWriter sw = new StreamWriter(file)) 
      { 
       sw.WriteLine(i); 
       Thread.Sleep(100); 
      } 
     } 
    } 
} 
+0

Ich bin ein bisschen wie ein Anfänger, wenn es um Dateioperationen geht. Suchet alles in den Speicher oder lädt es nur von Offset zu Offset + Länge? – jameszhao00

+0

Nach meinem Wissen wird die Suchoperation keine Daten laden und den Dateistrom nur an der angegebenen Position positionieren. In diesem Fall ist die Position, an der die neuen Daten beginnen. –