快速连续重写同一个文件?

时间:2010-01-29 20:59:59

标签: c# filesystems

我正在开发一个应用程序,它将保持正在运行的工作索引。

可以在工作会话结束时写一次,但我不想冒着丢失数据的风险。因此,每次用户进行新条目或更正时,我都会重写为磁盘(XML)。

private void WriteIndexFile()
{
    XmlDocument IndexDoc
    // Build document here

    XmlTextWriter tw = new XmlTextWriter(_filePath, Encoding.UTF8);
    tw.Formatting = Formatting.Indented;
    IndexDoc.Save(tw);
}

可以快速连续触发写入。如果发生这种情况,它会在先前的写入完成之前尝试打开文件进行写入。 (虽然这不正常,但我认为文件可能会被另一个程序打开使用。)

如何检查文件是否可以重写?

编辑以澄清:这是自动化实验室数据收集系统的一部分。用户将单击按钮以捕获数据(保存在单独的文件中),并识别数据包所针对的子任务。通常,点击之间的间隔为3-10分钟。

如果他们犯了错误,他们需要能够返回并更正错误,因此这不是仅限附加用法。

最后,文件将由其他自动化工具读取并由人工手动读取。 (XML / XSLT)

大小将受到限制,因为每个工作会话(工人班次或更少)将生成新的索引文件。

进一步的问题:由于压倒性的共识是不使用XML并以仅附加模式写入,我如何解决返回和纠正先前条目的要求?

我正在考虑使用“脏”标志,并在设置标志后和关闭工作会话后保存几分钟。如果在那段时间内发生了多次编辑,则只有一次写入 - 没有更快的用户 - 如果保存失败,也会有重试/取消对话框。想法?

5 个答案:

答案 0 :(得分:4)

在您的情况下,XML是一个糟糕的选择,因为必须在结束标记之前插入新内容。使用Text istead并只需打开要追加的文件并在文件末尾写下新内容,请参阅How to: Open and Append to a Log File

您还可以查看一个简单的日志框架,如log4net,并使用它而不是自己处理低级文件。

答案 1 :(得分:1)

如果您只想要所有操作的简单日志,那么XML可能是错误的选择,因为如果不重写整个文件很难附加到XML文档,随着文件的增长,这将变得越来越慢。 / p>

我建议改为File.AppendText甚至更好:在应用程序的生命周期内保持文件打开并使用WriteLine

(哦,正如其他人所指出的,你需要lock来确保一次只有一个线程写入文件。即使使用这个解决方案,这仍然是正确的。)

还有一些日志框架已经解决了这个问题,比如log4net。您是否考虑过使用现有的日志记录框架而不是自己编辑?

答案 2 :(得分:0)

我有一个使用System.Collections.Queue的记录器。基本上它等到排队等待然后尝试写它。在编写可能很慢的项目时,可以将更多项目添加到队列中。

这也有助于对邮件进行分组,而不是试图跟上。它在一个单独的线程上运行。

private AutoResetEvent ResetEvent { get; set; }

LogMessage(string fullMessage)
{
    this.logQueue.Enqueue(fullMessage);

    // Trigger the Reset Event to send the 
    this.ResetEvent.Set();
}

private void ProcessQueueMessages()
{
    while (this.Running)
    {
        // This will process all the items in the queue.
        while (this.logQueue.Count > 0)
        {
            // This method will just log the top item on the queue
            this.LogQueueItem();
        }

        // Once the queue is empty will wait for a 
            // another message to queueed before running again.  
        // Rather than sleeping and checking if the queue is full, 
            // saves from doing a System.Threading.Thread.Sleep(1000); stuff
        this.ResetEvent.WaitOne();
    }
}

我处理写入失败但没有出列,直到它写入文件没有错误。然后我继续尝试,直到它最终可以写。这节省了我,因为有人在此过程中从我们的某个应用程序中删除了权限。关闭我们的应用程序后返回权限,我们没有丢失一个日志声明。

答案 3 :(得分:0)

考虑使用平面文本文件。我有一个使用XML日志编写的进程......这是一个糟糕的选择。您无法在运行时写出状态,而无需不断重写文件以确保标记正确无误。如果它是写入文件的平面条目,你可以有一个自动时间轴,可以给你详细说明发生了什么,而不试图弄清楚它是否是XML编写器/标签集爆炸了你不必担心你的日志膨胀了。

答案 4 :(得分:0)

我同意其他人建议您避免使用XML。另外,我建议你有一个组件(一个“监视器”)负责所有文件的访问。该组件将负责处理多个并发请求并使磁盘写入一个接一个地发生。

相关问题