2010-01-29 21 views
2

我工作的一个应用程序,将让工作运行指数造诣。改写快速连续相同的文件?

可以在工作会议结束时写一次,但是我不想冒险失去数据,如果事情炸毁。因此,我重写到磁盘(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,并在仅附加模式写,我会怎么解决回去和纠正早期项目的要求?

我正在考虑有一个“脏”标志,标志设置后保存几分钟后关闭工作会议。如果在此期间发生多个编辑,则只会发生一次写入 - 没有更快的用户 - 如果保存失败,也会有重试/取消对话框。思考?

+0

当写入失败时你打算做什么?向用户报告并撤消?没有写会阻碍你继续下去? – 2010-01-29 21:09:18

+0

@Moron:这确实是主要问题。如果失败可以从优雅地恢复并且写作恢复,那么它是可以的。如果故障无法恢复(即某些其他未知应用将文件或磁盘锁定为已满),则继续丢失数据将是一种损失。 也许重试/取消对话框...? – mbmcavoy 2010-01-29 21:59:50

回答

1

如果你想要的是所有操作的一个简单的日志,XML可以在这里是错误的选择,因为它是难以追加到XML文档而无需重写整个文件,因为文件的增长,这将成为越来越慢。

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

(呵呵,正如其他人所指出的那样,你需要lock,以确保只有一个线程在同一时间写入文件。这仍然是真实的,即使这个解决方案。)

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

+0

也许他的PHB说它*必须*用XML。是的,XML是这项工作的错误工具,但是XML对许多工作来说都是错误的工具,它仍然在使用。有时尖括号会让我哭泣。 :'( – dss539 2010-01-29 21:13:05

+0

)并非所有更改都是简单附加,它基于用户输入,用户需要能够返回并更正错误。另外,有些属性可能会随着事情的进展而改变。 该文件需要“漂亮“超链接和其他进程的机器可读性 - 选择XML/XSLT的解决方案 最后,我并不太担心大小/写入性能 - 一个新文件将会频繁启动,我期望每一个最大〜50KB。 – mbmcavoy 2010-01-29 21:26:27

4

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

您也可以考虑像log4net一个简单的日志框架并使用,而不是处理低级文件的东西urself。

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(); 
    } 
} 

我处理写入失败但没有出队,直到写入文件没有错误。然后我只是不停地尝试,直到它终于写出来。这节省了我,因为有人在我们的应用程序中删除了其中一个应用程序的权限。我们的应用程序关闭了权限,并且我们没有丢失单个日志语句。

0

考虑使用平面文本文件。我有一个使用XML日志编写的进程......这是一个糟糕的选择。您无需在运行时直接写出状态,而无需不断重写文件以确保标签正确。如果它是写入文件的平面条目,那么您可以使用自动时间轴,可以让您知道发生了什么情况的详细信息,而无需弄清楚它是否是XML写入器/标记集发生爆炸,而且您不必担心自己的问题日志一样膨胀。

0

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