Как определить, был ли очищен буфер файлов

Это более короткая версия.

RegExp.escape = function(s) {
    return s.replace(/[$-\/?[-^{|}]/g, '\\$&');
}

Это включает неметаные символы из %, &, ' и ,, но спецификация JavaScript RegExp позволяет это.

1
задан martijn 23 January 2019 в 14:16
поделиться

2 ответа

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

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

Вот мой рабочий код:

[TestClass]
public class FileWriteTests
{

    [TestMethod]
    public void TestMethodAfterClose_filetailing()
    {

        var currentDir = Environment.CurrentDirectory;
        var fileToMonitor = "test.txt";
        File.Delete(Path.Combine(currentDir, fileToMonitor));
        List<string> output = new List<string>();
        using (var watcherTest = new PersonalFileTail(currentDir, fileToMonitor))
        {
            watcherTest.StartTail(delegate (string line) { output.Add(line); });
            using (var writer = new StreamWriter(Path.Combine(currentDir, fileToMonitor), true))
            {
                writer.WriteLine($"test");
                writer.Flush();
            }
            System.Threading.Thread.Sleep(200);
            watcherTest.StopTail();
        }
        System.Threading.Thread.Sleep(10);
        Assert.AreEqual(1, output.Count);
        Assert.AreEqual("test", output[0]);
    }

    [TestMethod]
    public void TestMethodAfterFlush_filetailing()
    {
        // initiate file
        var currentDir = Environment.CurrentDirectory;
        var fileToMonitor = "test.txt";
        File.Delete(Path.Combine(currentDir, fileToMonitor));
        FileInfo info = new FileInfo(Path.Combine(currentDir, fileToMonitor));

        List<string> output = new List<string>();
        using (var watcherTest = new PersonalFileTail(currentDir, fileToMonitor))
        {
            watcherTest.StartTail(delegate (string line) { output.Add(line); });
            using (var writer = new StreamWriter(Path.Combine(currentDir, fileToMonitor), true))
            {
                try
                {
                    writer.WriteLine($"test");
                    writer.Flush();
                    System.Threading.Thread.Sleep(1000);
                    Assert.AreEqual(1, output.Count);
                    Assert.AreEqual("test", output[0]);
                }
                catch
                {
                    Assert.Fail("Test failed");
                }
            }
            watcherTest.StopTail();
        }
    }

    public class PersonalFileTail : IDisposable
    {
        private string filename;
        private string directory;
        private Task fileTailTask;
        private Action<string> handleResults;
        private volatile bool runTask;
        private long lastFilePosition;
        public string FileName
        {
            get { return Path.Combine(directory, filename); }
        }
        public PersonalFileTail(string directory, string filename)
        {
            this.directory = directory;
            this.filename = filename;
            this.runTask = false;
            lastFilePosition = 0;
        }

        public void StartTail(Action<string> handleResults)
        {
            this.handleResults = handleResults;
            runTask = true;
            fileTailTask = Task.Run(() => MonitorFileTask());
        }

        public void StopTail()
        {
            runTask = false;
            fileTailTask.Wait();
        }

        public IEnumerable<string> ReadLinesFromFile()
        {
            using (StreamReader reader = new StreamReader(new FileStream(FileName,
            FileMode.Open, FileAccess.Read, FileShare.ReadWrite)))
            {
                string line = "";
                while ((line = reader.ReadLine()) != null)
                {
                    yield return line;
                }
                lastFilePosition = reader.BaseStream.Length;
            }
        }

        public void MonitorFileTask()
        {
            StreamReader reader = null;
            FileStream stream = null;
            try
            {
                using(stream = new FileStream(FileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
                using (reader = new StreamReader(stream))
                {
                    do
                    {
                        //if the file size has increased do something
                        if (reader.BaseStream.Length > lastFilePosition)
                        {
                            //seek to the last max offset
                            reader.BaseStream.Seek(lastFilePosition, SeekOrigin.Begin);

                            //read out of the file until the EOF
                            string line = "";
                            while ((line = reader.ReadLine()) != null)
                            {
                                handleResults(line);
                            }

                            //update the last max offset
                            lastFilePosition = reader.BaseStream.Position;
                        }
                        // sleep task for 100 ms 
                        System.Threading.Thread.Sleep(100);
                    }
                    while (runTask);
                }
            }
            catch
            {
                if (reader != null)
                    reader.Dispose();
                if (stream != null)
                    stream.Dispose();
            }
        }

        public void Dispose()
        {
            if(runTask)
            {
                runTask = false;
                fileTailTask.Wait();
            }
        }
    }
}

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

0
ответ дан martijn 23 January 2019 в 14:16
поделиться

К сожалению, Flush не смывает то, что вы хотите. Я нахожу много статей, чтобы объяснить это, например:

https://blogs.msdn.microsoft.com/alejacma/2011/03/23/filesystemwatcher-class-does-not-fire -change-events-when-notifyfilters-size-is-used /

Существует решение с .net 4, использовать другой метод перегрузки FileStream: Flush(bool)

[110 ]

А на реагирование диска дается только 10 мсек, может, это другая проблема.

0
ответ дан shingo 23 January 2019 в 14:16
поделиться
Другие вопросы по тегам:

Похожие вопросы: