我有一个由第三方应用程序编写的日志文件文件,我希望我的应用程序以真实/近时间为“读取”该日志文件,解析新的日志条目并对某些事件采取行动。

我的想法是,我可以通过FileSystemWatcher(以发出信号文件更改)和内存映射文件(继续从某个偏移量读取)的组合来实现这一目标。

但是,由于这是我第一次使用MemoryMappedFiles,因此我确实遇到了一些问题,这些问题可能是由于无法正确理解该概念而引起的(例如,我无法打开现有文件,因为它在其他过程中使用了)。

我想知道有人是否有一个示例说明如何使用MemoryMappedFiles读取另一个过程锁定的文件?

谢谢,

汤姆

编辑:

从评论中,似乎内存映射的文件无法帮助我访问具有独家锁定的文件。但是,例如Baretail(http://www.baremetalsoft.com/baretail/index.php)等“尾巴”工具可以做到这一点。阅读该文件,该文件以1S间隔从另一个应用程序中获得独家锁定)。那么,必须有某种方法可以做到这一点?

Editedit:

要回答我自己的问题,打开锁定文件的诀窍是,创建具有以下访问标志的文件流:

fileStream = new System.IO.FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Delete | FileShare.ReadWrite);
有帮助吗?

解决方案

为了回答我自己的问题,读取锁定文件的技巧是创建具有以下访问标志的文件流:

FileStream fileStream = new System.IO.FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Delete | FileShare.ReadWrite);

现在,这只是进行基于间隔的轮询或寻找Filesystemwatcher更改事件以检测文件更改的问题

其他提示

我不确定是否会为您提供帮助。看一下filestream:

var stream = new FileStream(path, FileMode.Open, FileShare.Read);
stream.Seek(offset, SeekOrigin.Begin);

尽管如果第三方应用程序专门锁定文件,那么您对此无能为力...

开始第二编辑

一个想法...

如果第三方应用程序碰巧使用了nlog,log4net或system.diargnostics等记录框架,则您仍然可以编写自己的目标/appender/tracelistener,并将消息路由您可以查看的消息(例如作为文件,不专门开放,其他过程等)。

如果您的第三方应用程序正在使用伐木框架,那么我们现在可能会听到它;-)

结束第二编辑

开始编辑

我想我误解了这个问题。起初听起来像您使用的第三方库,该库已实施了日志记录,并且您想从生成日志记录的程序中进行解析。重读您的问题后,听起来您想从应用程序外部“收听”日志文件。如果是这样,我的答案可能不会帮助您。对不起。

结束编辑

我没有关于MemoryMappingFiles的任何内容,但是我想知道您是否可以通过为第三方记录系统编写自定义侦听器/目标/Appender来实现自己的目标?

例如,如果您使用的是NLOG,则可以编写自定义目标并指导所有记录消息(同时还将其引导到“真实”目标)。这样,您会在记录时会在每个日志消息中获得破解(因此实际上是实时的,而不是实时的)。您可以使用log4net和system.diagnostics做同样的事情。

请注意,NLOG甚至具有“ MethodCall”目标。要使用它,您只需要编写具有正确签名的静态方法。我不知道log4net是否具有与此相似的概念。

这似乎比第三方软件编写的日志文件更容易可靠地工作。

如果文件正在“使用”,则无能为力。它确实是“使用”。 MemoryMappedFiles是用于从驱动器上读取大量数据,或者与其他程序共享数据。这将无助于解决“使用”限制。

内存映射的文件与您初始化的文件流相同的限制,请确保您初始化内存映射文件

var readerStream = new fileStream(路径,filemode.open,fileaccess.read,fileShare.ReadWrite);

var mmf = memorymappedfile.createfile(readerStream,null,0,memorymappedfileAccess.Read,null,handleInheribality.none,false);

如果某些其他过程即使写作也完全锁定了它,那么您不确定是否有办法解决。也许使用某些计时器确实检测到该过程何时停止写入。

我做了类似的事情,仅用于监视控制台上的日志文件(而不是处理),但是原理是相同的。像您一样,我使用Filesystemwatcher,而重要的逻辑是我的事件处理程序:

case WatcherChangeTypes.Changed:
{
    System.IO.FileInfo fi = new FileInfo(e.FullPath);

    long prevLength;

    if (lastPositions.TryGetValue(e.FullPath, out prevLength))
    {
        using (System.IO.FileStream fs = new FileStream(
           e.FullPath, FileMode.Open, FileAccess.Read))
        {
            fs.Seek(prevLength, SeekOrigin.Begin);
            DumpNewData(fs, (int)(fi.Length - prevLength));
            lastPositions[e.FullPath] = fs.Position;
        }
    }
    else
      lastPositions.Add(e.FullPath, fi.Length);

    break;
}

最后位置在哪里

Dictionary<string, Int64> lastPositions = new Dictionary<string, long>();

和DelmbNewData简直就是

private static void DumpNewData(FileStream fs, int bytesToRead)
{
    byte[] bytesRead = new byte[bytesToRead];
    fs.Read(bytesRead, 0, bytesToRead);
    string s = System.Text.ASCIIEncoding.ASCII.GetString(bytesRead);
    Console.Write(s);
}
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top