我有一个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).
答案 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();
}