2010-03-03 3 views
9

Sous Linux, une grande partie de l'IPC est effectuée en ajoutant un fichier dans un processus et en lisant le nouveau contenu d'un autre processus.Lecture des modifications du contenu du fichier dans .NET

Je veux faire ce qui précède dans Windows/.NET (Trop désordonné pour utiliser IPC normal tels que les tuyaux). J'ajoute à un fichier d'un processus Python, et je veux lire les changements et SEULEMENT les changements chaque fois que FileSystemWatcher rapporte un événement. Je ne veux pas lire le contenu du fichier entier en mémoire chaque fois que je cherche des changements (le fichier sera énorme)

Chaque opération d'ajout ajoute une rangée de données qui commence par un compteur incrémentant unique (horodatage + clé) et se termine par une nouvelle ligne.

Répondre

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

cela va vous aider à lire des lignes seulement jointes

+0

ont été testés et cela fonctionne. Technique assez cool. –

+0

Une excellente solution, courte et mortelle! – MaYaN

9

Vous pouvez stocker le décalage de la dernière opération de lecture et rechercher le fichier à ce décalage lorsque vous recevez une notification de fichier modifié. Voici un exemple:

méthode principale:

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

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

    WriteToFile(); 
} 

Lire à partir méthode de fichier:

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

Ecrire à déposer Méthode:

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

Je suis un peu un noob quand il s'agit d'opérations de fichiers. Est-ce que le chargement cherche tout en mémoire ou est-ce qu'il charge seulement de l'offset à l'offset + la longueur? – jameszhao00

+0

À ma connaissance, l'opération de recherche ne chargera aucune donnée et positionnera simplement le flux de fichier à la position spécifiée. Dans ce cas, la position sera l'endroit où les nouvelles données commencent. –

Questions connexes