带有ReadLines()的FileSystemWatcher。Last()错过了一些新行

时间:2014-12-23 16:17:29

标签: c#

我有一个FileSystemWatcher,用于将文件大小更改为聊天记录。

OnChanged()事件我有File.ReadLines()。Last()来获取新行,因为这就是我想要的。

这一切都很有效,除了它错过了一些新线路,因为它们可以同时出现。

我应该怎么做才能跟踪所有新行?

private string _folderMyDocuments = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);

    public void RunWatcher()
    {
        var watcher = new FileSystemWatcher(_folderMyDocuments + @"\Entropia Universe\", "chat.log");
        watcher.NotifyFilter = NotifyFilters.Size;
        watcher.Changed += new FileSystemEventHandler(OnChanged);
        watcher.EnableRaisingEvents = true;
    }

    private void OnChanged(object source, FileSystemEventArgs e)
    {
        var regex = new Regex(@"^(?<Date>\d{4}-\d{2}-\d{2})\s(?<Time>\d{2}\:\d{2}\:\d{2})\s(?:\[(?:Team|Force)\]\s\[\]\s)(?<User>.+)(?:\sreceived\s)(?<Item>[^\(]+)(?:(?:\s\((?:(?<Amount>\d+|\w+)).+$)|\.$)$");
        var readLine = File.ReadLines(_folderMyDocuments + @"\Entropia Universe\chat.log").Last();
        var match = regex.Match(readLine);

        if(match.Success)
        {
            Dispatcher.Invoke(() =>
            {
                RTB1.AppendText(
                    match.Groups["Date"] + " " +
                    match.Groups["Time"] + " " +
                    match.Groups["User"] + " " +
                    match.Groups["Item"] + " " +
                    match.Groups["Amount"] + 
                    "\r");
            });
        }
    }

示例日志

2013-12-21 16:26:13 [Force] [] PP received a Combustive Attack Nanochip VII (L).
2014-12-23 14:53:27 [Team] [] ms received Shrapnel (5372).
2014-12-23 14:53:27 [Team] [] ms received Weapon Cells (9649).
2014-12-23 14:53:27 [Team] [] ms received Socket I Component (13)."
2014-12-23 14:53:27 [Team] [] ms received a Animal Oil Residue.
2014-12-23 14:53:27 [Team] [] ms received BLP Pack (71).

2 个答案:

答案 0 :(得分:0)

除了跳过行之外,每次触发OnChanged时,您的解决方案也会重新读取整个文件 - 它的效率非常低。

您需要做的是跟踪上次已知的文件大小,并从该位置继续读取。这将解决这两个问题。

另请注意,File.ReadLines会锁定文件以供阅读。如果您正在监视另一个进程不断更新的文件,这可能不是您想要的。打开文件时,请确保为其提供完整的文件共享,以便没有锁定。

答案 1 :(得分:0)

终于搞定了。

我记录了文件中的行数(_lineCount),在OnChanged事件发生后,我读了很多行去新行,然后在新行上进行正则表达式匹配。

效率不高,但我的文件总是很小(最大10mb),所以这不应该造成任何问题。

readonly string _folderMyDocuments = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
private int _lineCount;

public void RunWatcher()
    {
        var watcher = new FileSystemWatcher(_folderMyDocuments + @"\Entropia Universe\", "chat.log");
        watcher.NotifyFilter = NotifyFilters.Size;
        watcher.Changed += OnChanged;
        watcher.EnableRaisingEvents = true;
    }

    private void OnChanged(object source, FileSystemEventArgs e)
    {
        var regex =
            new Regex(
                @"^(?<Date>\d{4}-\d{2}-\d{2})\s(?<Time>\d{2}\:\d{2}\:\d{2})\s(?:\[(?:Team|Force)\]\s\[\]\s)(?<User>.+)(?:\sreceived\s)(?<Item>[^\(]+)(?:(?:\s\((?:(?<Amount>\d+|\w+)).+$)|\.$)$",
                RegexOptions.Compiled);

        using (var sr = new StreamReader(_folderMyDocuments + @"\Entropia Universe\chat.log"))
        {
            for (var i = 0; i < _lineCount; i++)
            {
                sr.ReadLine();
            }

            while (!sr.EndOfStream)
            {
                var newLines = sr.ReadLine();

                if (newLines != null)
                {
                    _lineCount++;
                    foreach (Match match in regex.Matches(newLines))
                    {
                        Dispatcher.Invoke(() =>
                        {
                            RTB1.AppendText(
                                match.Groups["Date"] + " " +
                                match.Groups["Time"] + " " +
                                match.Groups["User"] + " " +
                                match.Groups["Item"] + " " +
                                match.Groups["Amount"] + "\r"
                                );
                        });
                    }
                }

            }
        }
    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        BTN_Start.IsEnabled = false;
        using (var r = new StreamReader(_folderMyDocuments + @"\Entropia Universe\chat.log"))
        {
            while ((r.ReadLine()) != null)
            {
                _lineCount++;
            }
        }
        RunWatcher();
    }