c#XML或替代方案

时间:2012-02-08 16:15:24

标签: c# xml

我正在开发一个程序来记录来自传入串行通信的数据。我必须通过发送命令来调用串行盒来接收一些东西。这一切都很好,但我有一个问题。

该程序必须从上网本(约1.5 gHZ,2 gig ram)运行,当我要求它将这些信息保存到XML文件时,它无法跟上。

我每隔5秒才收到一次通讯,我不是在任何地方读文件。

我使用xml.save(字符串文件名)来保存文件。

还有另一种更好的方法是将信息保存到我的XML中,还是应该使用替代方法?

如果我应该使用替代品,它应该是什么?

编辑: 添加了一些代码:

            XmlDocument xml = new XmlDocument();
            xml.Load(logFile);

            XmlNode p = xml.GetElementsByTagName("records")[0];
            for (int i = 0; i < newDat.Length; i++)
            {
                XmlNode q = xml.CreateElement("record");

                XmlNode a = xml.CreateElement("time");
                XmlNode b = xml.CreateElement("temp");
                XmlNode c = xml.CreateElement("addr");

                a.AppendChild(xml.CreateTextNode(outDat[i, 0]));
                b.AppendChild(xml.CreateTextNode(outDat[i, 1]));
                c.AppendChild(xml.CreateTextNode(outDat[i, 2]));

                sendTime = outDat[i, 0];

                points.Add(outDat[i, 2], outDat[i, 1]);

                q.AppendChild(a);
                q.AppendChild(b);
                q.AppendChild(c);

                p.AppendChild(q);
            }

            xml.AppendChild(p);
            xml.Save(this.logFile);

这是与XML相关的代码,每5秒运行一次。我正在阅读(我没有错误),添加一些孩子,然后再次保存。当我保存时,我得到了错误。

5 个答案:

答案 0 :(得分:6)

您可能希望查看使用XMLWriter并手动构建XML文件 。这将允许您打开文件并在日志记录期间保持打开状态,在读取数据时一次附加一个XML片段。 XMLReader类针对仅向前写入XMLStream进行了优化。

与使用Save方法在每次读取数据时序列化(保存)完整的XML文档以及最后只想在末尾添加新片段相比,上述方法应该快得多。

修改

根据您发布的代码示例,加载和保存会导致不必要的性能瓶颈。每次添加日志条目时,您实际上都会加载完整的XML文档,并在后台将其解析为完整的XML树。然后修改树(通过添加节点),然后再将其全部序列化为磁盘。这非常适得其反。

我建议的解决方案真的是要走的路:只创建和打开一次日志文件;然后每次读取新数据时,使用XMLWriter逐个写出XML元素;这样你就不会在内存中保存XML日志的全部内容,而只是在文件末尾附加小块数据 - 这在开销方面应该是不可察觉的;最后,只需关闭根XML标记,关闭XMLWriter并关闭文件。而已!即使您在UI线程上同步实现它,也可以保证不会降低UI的速度。

答案 1 :(得分:1)

虽然不能直接回答你的问题,但听起来你是以非常线性的方式做所有事情:

  1. 接收命令
  2. 在内存中修改XML
  3. 将内存XML保存到磁盘
  4. GoTo 1
  5. 我建议你考虑使用一些线程,或者可能Task来使这更加异步。这肯定会更加困难,你必须与任务同步搏斗,但从长远来看,它会表现得更好。

    我会看到一个线程(可能是主线程,不确定你是否使用WinForms,一个控制台应用程序或什么)接收命令,并将“更改”发布到一个保持类。然后有第二个线程,它定期轮询这个保持类并检查它是否为“脏”状态。当它检测到此状态时,它会抓取XML的副本并将其保存到磁盘。

    这使您的串行通信能够不间断地继续运行,无论您运行的硬件的性能有多差。

答案 2 :(得分:1)

通常对于日志文件,一个选择附加友好格式,否则每次需要追加新记录并保存结果时都必须重新解析整个文件。纯文本CSV可能是最简单的选项。

如果您需要具有类似XML的文件,则另一个选项是存储XML片段列表而不是完整XML。这样你仍然可以使用XML API(XmlReader可以在XmlReader.Create调用的XmlReaderSettings中指定ConformanceLevel.Frament时读取片段),但是你不需要重新读取整个文档来附加新条目 - 简单文件级追加就够了。即WCF日志以这种方式编写。

答案 3 :(得分:0)

如果您的输出必须是XML格式的文件,那么@Miky Dinescu的答案就是这样做的一种方法。原因是您每次添加另一个条目时都要求它完成加载并重新分析整个XML文件。加载和解析XML文件会使文件越大,IO,内存和CPU密集程度越来越大。因此,如果必须在非常有限的时间范围内运行,任何硬件的开销都不会很长。否则,您需要重新考虑整个过程,并且可以简单地将所有数据缓冲到内存缓冲区中,您可以以更加悠闲的速度写出(刷新)。

答案 4 :(得分:0)

我做了这项工作,但我不相信这是“最佳实践”方法。

我有另一个班级,我的XmlDocument一直在运行,然后尝试以保存每次添加数据。如果失败,它只是等待下次保存。

我会建议其他人看看Miky Dinescu的建议。我只是觉得自己很想改变如何保存数据。