Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/280.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 快速连续重写同一个文件?_C#_Filesystems - Fatal编程技术网

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

C# 快速连续重写同一个文件?,c#,filesystems,C#,Filesystems,我正在开发一个应用程序,它将保持工作的运行索引 我可以在工作会议结束时写一次,但我不想在发生故障时冒丢失数据的风险。因此,每当用户做出新条目或更正时,我都会将其重写到磁盘(XML) private void WriteIndexFile() { XmlDocument IndexDoc // Build document here XmlTextWriter tw = new XmlTextWriter(_filePath, Encoding.UTF8); tw

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

我可以在工作会议结束时写一次,但我不想在发生故障时冒丢失数据的风险。因此,每当用户做出新条目或更正时,我都会将其重写到磁盘(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并以仅附加模式编写,我如何解决返回并更正早期条目的要求


我正在考虑设置一个“脏”标志,并在设置标志和关闭工作会话后节省几分钟时间。如果在这段时间内进行了多次编辑,则只会发生一次写入操作-用户不会更快-如果保存失败,还会出现重试/取消对话框。想法?

如果您只需要一个所有操作的简单日志,那么在这里选择XML可能是错误的,因为在不重写整个文件的情况下,很难将XML附加到XML文档中,而整个文件会随着文件的增长而变得越来越慢

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

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


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

XML在您的案例中是一个糟糕的选择,因为必须在结束标记之前插入新内容。使用文本istead,只需打开文件进行追加,并在文件末尾写入新内容,请参阅


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

我有一个使用
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();
    }
}

我会处理写入失败,但不会退出队列,直到它写入到没有错误的文件。然后我继续尝试,直到它最终可以写。这救了我,因为有人在it过程中从我们的一个应用程序中删除了权限。权限在没有关闭我们的应用程序的情况下被授予,并且我们没有丢失一条日志语句。

考虑使用平面文本文件。我有一个使用XML日志编写的流程。。。这是一个糟糕的选择。您不能在运行时写出状态,而不必不断重写文件以确保标记正确。如果是简单的条目写入到文件中,您可以有一个自动的时间线,它可以为您提供所发生事情的详细信息,而不必试图找出是XML编写器/标记集爆炸了,您也不必担心日志会膨胀太多。

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

写入失败时,您打算怎么做?向用户报告并撤消?写不好会不会妨碍你继续写下去?@白痴:这才是主要问题。如果故障可以正常恢复并继续写入,那么就可以了。如果无法恢复故障(即,其他未知应用程序锁定文件或磁盘已满),则继续并丢失数据将是一种损失。也许是重试/取消对话框…?也许他的PHB说它必须是XML格式的。是的,XML对于工作来说是错误的工具,但是XML对于许多工作来说是错误的工具,并且它仍然被使用。有时尖括号让我哭(并非所有更改都是简单的附件。它基于用户输入,用户需要能够返回并更正错误。此外,某些属性可能会随着事情的进展而更改。文件需要“漂亮”具有超链接,并可供其他进程机器读取-XML/XSLT是选择的解决方案。最后,我不太担心大小/写入性能。-将经常启动一个新文件,我希望每个文件的最大大小约为50KB。