如何监控正被占用的日志文件长度变化并读取新增内容?
解决被占用日志文件的监控与新增行读取问题
ReadAllLines会以独占锁打开文件,这就是它在文件被占用时报错的原因。要解决这个问题,你需要以共享读写权限打开文件流,同时记录上次读取的位置,每次只读取新增的内容。
核心实现思路
- 维护一个变量记录上次读取到的文件位置,初始值为0
- 点击按钮时,以共享模式打开文件流,跳过已读取的部分,直接读取新增内容
- 将新增内容拆分为行,更新标签显示新增行数,同时可以处理每一行日志
- 更新读取位置为当前文件长度,供下次检查使用
代码示例(以C# WinForms为例)
首先在窗体类中定义全局变量:
private long _lastReadPosition = 0; // 替换为你的日志文件路径 private readonly string _logFilePath = @"C:\your\log\path\app.log";
然后实现按钮点击事件:
private void btnCheckLogChanges_Click(object sender, EventArgs e) { try { using (var fileStream = new FileStream(_logFilePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) using (var streamReader = new StreamReader(fileStream)) { // 定位到上次读取结束的位置 fileStream.Seek(_lastReadPosition, SeekOrigin.Begin); // 读取所有新增内容 string newContent = streamReader.ReadToEnd(); if (!string.IsNullOrWhiteSpace(newContent)) { // 拆分新增内容为行(自动适配系统换行符) string[] newLines = newContent.Split(new[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries); // 更新标签显示新增行数 lblLineChange.Text = $"新增行数: {newLines.Length}"; // 遍历处理每一行新增日志(按需修改逻辑) foreach (string line in newLines) { // 示例:将新增行添加到列表框 listBoxLog.Items.Add(line); } } // 更新读取位置为当前文件总长度 _lastReadPosition = fileStream.Length; } } catch (FileNotFoundException) { lblLineChange.Text = "错误:日志文件不存在"; } catch (UnauthorizedAccessException) { lblLineChange.Text = "错误:无权限访问日志文件"; } catch (Exception ex) { lblLineChange.Text = $"错误:{ex.Message}"; } }
额外优化建议
- 如果需要自动持续监控,可以添加
Timer控件,设置固定间隔(比如1000ms),在Timer.Tick事件中执行上述核心逻辑 - 若日志文件使用非UTF-8编码,需在
StreamReader构造时指定编码,例如:new StreamReader(fileStream, Encoding.GetEncoding("GB2312")) - 处理超大日志文件时,可以考虑分批读取,避免一次性加载过多内容到内存
内容的提问来源于stack exchange,提问作者Jack
相关产品推荐
相关产品推荐

