В Linux большая часть IPC выполняется путем добавления файла в один процесс и чтения нового содержимого из другого процесса.

Я хочу сделать это в Windows / .NET (слишком беспорядочно использовать обычные IPC, такие как каналы). Я добавляю файл из процесса Python и хочу читать изменения и ТОЛЬКО изменения каждый раз, когда FileSystemWatcher сообщает о событии. Я не хочу читать все содержимое файла в память каждый раз, когда ищу изменения (файл будет огромным)

Каждая операция добавления добавляет строку данных, которая начинается с уникального увеличивающегося счетчика (отметка времени + ключ) и заканчивается новой строкой.

11
jameszhao00 3 Мар 2010 в 19:38

2 ответа

Лучший ответ
    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());            
            }
        }
    }

Это поможет вам читать только добавленные строки

29
Robert Harvey 3 Мар 2010 в 20:29
ОТЛИЧНОЕ решение, короткое и смертельное!
 – 
MaYaN
6 Апр 2016 в 17:50

Вы можете сохранить смещение последней операции чтения и искать файл по этому смещению, когда получите уведомление об изменении файла. Пример ниже:

Основной метод:

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

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

    WriteToFile();
}

Чтение из файла:

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

Запись в файл методом:

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);
            }
        }
    }
}
11
João Angelo 3 Мар 2010 в 20:33
Я немного новичок, когда дело касается файловых операций. Поиск загружает все в память или загружается только от смещения до смещения + длины?
 – 
jameszhao00
3 Мар 2010 в 20:49
Насколько мне известно, операция поиска не загружает никаких данных, а просто помещает файловый поток в указанную позицию. В этом случае позиция будет там, где начинаются новые данные.
 – 
João Angelo
3 Мар 2010 в 21:10