在C#中,有没有办法将XML节点添加到磁盘上的文件而不先加载它?

时间:2011-01-23 11:31:59

标签: c# xml

我在磁盘上有一个非常基本的XML结构/文件,类似于:

<root>
    <data timestamp="dd-mm-yyyy" type="comment">kdkdkdk</data>
    <data timestamp="dd-mm-yyyy" type="event">kdkdkdkgffgfdgf</data>
    <data timestamp="dd-mm-yyyy" type="something">kddsdsfsdkdkdk</data>
</root>

如上所述,XML将位于磁盘上的外部文件中。由于文件可能会变得相当大(实际上每隔几周会被“修剪”),我不想先加载XML文件来添加新节点......

有没有办法添加这样的新节点?它可以被添加到顶部/底部等,因为实际使用XML的进程无论如何都按时间戳排序..

我猜测粗略的方法是将节点附加为文本..但是我认为会在结束标记之后添加节点吗?

任何想法都感激不尽...... 大卫。

8 个答案:

答案 0 :(得分:8)

不使用任何XML API或工具。

您可以将文件打开为文本,找到</root>的位置并从那里开始覆盖。当然,再次添加</root>


快速而肮脏的方法,这不是很强大:

  • 确保准备初始文件,结束标记后应该(无空格)
  • 确保使用ASCII或UTF8编码

====

string closeTag = "</root>";
int closeLength = Encoding.UTF8.GetBytes(closeTag).Length;

var fs = System.IO.File.Open(filename, System.IO.FileMode.Open);
fs.Position = fs.Length - closeLength;

var writer = new StreamWriter(fs);  // after the Position is set

writer.WriteLine(newTag);
writer.Write(closeTag);  // NOT WriteLine !!

writer.Close();
fs.Close();

当然,您知道使用using() {}块。

答案 1 :(得分:4)

不知何故,您必须阅读XML文件,因为您不能只是在文档中添加节点。

Xml文件只能有一个根,因此必须在最后一个数据元素之后添加新节点,但是必须在根结束标记之前添加。否则xml无效。

答案 2 :(得分:2)

这里已经有很多不错的答案了,但是为了再次提出这个问题,你确定这些数据需要存储为XML文件吗?

您存储的数据看起来相当简单(即包含三个字段,日期,类型和一些字符串数据的记录。如果您不需要XML提供的任何附加好处(see here),那么为什么不只使用基本的CSV?这样你只需通过File.AppendText("filename")就像日志文件一样追加它。

(天啊,甚至可以使用像log4net这样的东西来管理日志记录和任何清理内务管理。)

答案 3 :(得分:1)

取决于

如果您想以“正确”的方式执行此操作,则必须阅读文件及其中的XML。例如,您可以使用XmlReader类来避免将其完全加载到内存中。

但是,如果你绝对知道文本的布局和文件的编码,你可以通过打开它作为随机访问文件(FileStream)来避免完全阅读和重写它,跳到最后(减去“&lt; root /&gt;”),在那里添加新条目并写下“&lt; root /&gt;”试。

答案 4 :(得分:1)

在没有阅读完整文件的情况下,我看不到一种方法可以做你正在做的事情,但作为一种解决方法,你可以将文件视为纯文本,即没有根节点(它将是无效的XML) 。然后,您可以将新节点作为纯文本添加到文件中。而且,由于您的XML解析过程无论如何都会加载整个文件,因此它可以在将根节点视为XML之前添加它。

答案 5 :(得分:1)

System.IO.FileInfo[] aryFi = di.GetFiles("*.xml");


foreach (System.IO.FileInfo fi in aryFi) {

 System.Xml.XmlDocument xmlDocument = new System.Xml.XmlDocument();
 xmlDocument.Load(fi.FullName);

 XmlNode refelem = xmlDocument.LastChild;
 XmlNode newElem = xmlDocument.CreateNode("element", "something", "");
 newElem.InnerText = "sometext";
 xmlDocument.InsertAfter(newElem, refelem);
}

我相信打开和插入节点是最佳选择。无论哪种方式,你都需要使用IO,为什么不采用正确的方法呢?

单个文件

System.Xml.XmlDocument xmlDocument = new System.Xml.XmlDocument();
 xmlDocument.Load("file path");

 XmlNode refelem = xmlDocument.LastChild;
 XmlNode newElem = xmlDocument.CreateNode("element", "something", "");
 newElem.InnerText = "sometext";
 xmlDocument.InsertAfter(newElem, refelem);

答案 6 :(得分:1)

如果不加载XML,则表示不构建DOM树,VTD-XML是唯一允许您逐步剪切粘贴拆分或修改的API。此外,由于VTD-XML具有内存效率,因此您不必担心XML文档的大小。 Java中的类似帖子位于How to update large XML file。请注意,vtd-xml在Java,C#,C和C ++中可用。

答案 7 :(得分:-3)

只需使用

string s = File.ReadAllText(path)
s = s.replace("</root>", newnode + "</root>")
File.WriteAllText(s, path)