2010-03-03 20 views
9

W systemie Linux wiele IPC wykonuje się poprzez dołączenie do pliku w jednym procesie i odczytanie nowej zawartości z innego procesu.Czytanie zmian zawartości pliku w .NET

Chcę zrobić powyższe w Windows/.NET (Zbyt brudny, aby używać normalnego IPC, takich jak rury). Dołączam do pliku z procesu Python i chcę przeczytać zmiany i TYLKO zmiany za każdym razem, gdy FileSystemWatcher zgłasza zdarzenie. Nie chcę czytać całej zawartości pliku w pamięci za każdym razem, gdy szukam zmian (plik będzie ogromny)

Każda operacja dołączania dodaje wiersz danych rozpoczynający się od unikalnego licznika zwiększającego (znacznik czasu + klawisz) i kończy się znakiem nowej linii.

Odpowiedz

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

to pomoże Ci odczytać tylko dołączone linie

+0

Przetestowane, to działa. Całkiem fajna technika. –

+0

WIELKIE rozwiązanie, krótkie i śmiertelne! – MaYaN

9

można zapisać przesunięcie ostatniej operacji odczytu i szukać pliku do offsetu że gdy pojawi się powiadomienie o zmienionych plików. Przykładem następująco:

główne metody:

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

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

    WriteToFile(); 
} 

odczytać z metodą Plik:

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

zapisać do pliku metoda:

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

Jestem trochę noob, jeśli chodzi o operacje na plikach. Czy chcesz załadować wszystko do pamięci lub czy ładuje się tylko od przesunięcia do przesunięcia + długości? – jameszhao00

+0

Z mojej wiedzy operacja wyszukiwania nie załaduje żadnych danych i po prostu umieści strumień plików w określonej pozycji. W takim przypadku pozycja będzie znajdować się w miejscu, w którym rozpoczynają się nowe dane. –