将新节点添加到xml结尾的最快方法?

我有一个大的xml文件(大约10 MB)以下简单的结构:

 ....... ....... ....... ....... .......  

我需要在标记之前的末尾添加一个新节点。 什么是在.net中实现这一目标的最快方法?

您需要使用XML包含技术。

你的error.xml(不会改变,只是一个存根。由XML解析器用来读取):

   ]>  &logrows;  

你的errorsrows.txt文件(更改,xml解析器不理解它):

 .... .... .... 

然后,向errorsrows.txt添加一个条目:

 using (StreamWriter sw = File.AppendText("logerrors.txt")) { XmlTextWriter xtw = new XmlTextWriter(sw); xtw.WriteStartElement("Error"); // ... write error messge here xtw.Close(); } 

或者您甚至可以使用.NET 3.5 XElement,并将文本附加到StreamWriter

 using (StreamWriter sw = File.AppendText("logerrors.txt")) { XElement element = new XElement("Error"); // ... write error messge here sw.WriteLine(element.ToString()); } 

另请参阅Microsoft的文章“修改大型XML文件的高效技术”

首先,我将取消System.Xml.XmlDocument的资格,因为它是一个DOM ,它需要在可以附加到内存之前解析并构建内存中的整个树。 这意味着您的10 MB文本内存将超过10 MB。 这意味着它是“内存密集型”和“耗时”。

其次,我会取消System.Xml.XmlReader的资格,因为它需要首先解析整个文件,然后才能到达可以附加到它的位置。 您必须将XmlReader复制到XmlWriter中,因为您无法修改它。 这需要先将内存中的XML复制,然后再附加到它。

XmlDocument和XmlReader的更快解决方案是字符串操作(它有自己的内存问题):

 string xml = @"..."; int idx = xml.LastIndexOf(""); xml = xml.Substring(0, idx) + "new error"; 

切掉结束标记,添加新错误,然后添加结束标记。

我想你可能会对此发疯,并将你的文件截断9个字符并附加到它上面。 不必读入文件并让操作系统优化页面加载(只需加载最后一个块或其他东西)。

 System.IO.FileStream fs = System.IO.File.Open("log.xml", System.IO.FileMode.Open, System.IO.FileAccess.ReadWrite); fs.Seek(-("".Length), System.IO.SeekOrigin.End); fs.Write("new error"); fs.Close(); 

如果您的文件为空或仅包含“<错误> ”,则会出现问题,通过检查长度可以轻松处理这两个问题。

最快的方法可能是直接文件访问。

 using (StreamWriter file = File.AppendText("my.log")) { file.BaseStream.Seek(-"".Length, SeekOrigin.End); file.Write(" New error message."); } 

但是你丢失了所有漂亮的XMLfunction,可能很容易破坏文件。

我会使用XmlDocument或XDocument加载您的文件,然后相应地操作它。

然后我会看看在内存中缓存此XmlDocument的可能性,以便您可以快速访问该文件。

你需要什么速度? 你有性能瓶颈还是期待?

试试这个:

  var doc = new XmlDocument(); doc.LoadXml("This is my first error"); XmlNode root = doc.DocumentElement; //Create a new node. XmlElement elem = doc.CreateElement("error"); elem.InnerText = "This is my error"; //Add the node to the document. if (root != null) root.AppendChild(elem); doc.Save(Console.Out); Console.ReadLine(); 

您的XML文件如何在代码中表示? 你使用System.XML类吗? 在这种情况下,您可以使用XMLDocument.AppendChild。

以下是如何在C中实现它,.NET应该是类似的。

游戏是简单地跳转到文件的末尾,跳过标签,追加新的错误行,然后写一个新的标签。

 #include  #include  #include  int main(int argc, char** argv) { FILE *f; // Open the file f = fopen("log.xml", "r+"); // Small buffer to determine length of \n (1 on Unix, 2 on PC) // You could always simply hard code this if you don't plan on // porting to Unix. char nlbuf[10]; sprintf(nlbuf, "\n"); // How long is our end tag? long offset = strlen(""); // Add in an \n char. offset += strlen(nlbuf); // Seek to the END OF FILE, and then GO BACK the end tag and newline // so we use a NEGATIVE offset. fseek(f, offset * -1, SEEK_END); // Print out your new error line fprintf(f, "New error line\n"); // Print out new ending tag. fprintf(f, "\n"); // Close and you're done fclose(f); } 

最快的方法可能是使用XmlReader在文件中读取,并使用XmlWriter简单地将每个读取节点复制到新流当您到达遇到结束标记的点时,您只需要在继续“读取和复制”循环之前输出您的附加元素。 这种方式不可避免地要比将整个文档读入DOM( XmlDocument类)更难,但对于大型XML文件来说, 快得多。 不可否认,使用StreamReader / StreamWriter会更快一些,但在代码中工作非常可怕。

使用基于字符串的技术(比如寻找文件的末尾,然后向后移动结束标记的长度)很容易受到文档结构中意外但完全合法的变化的影响。

该文档可以以任何数量的空白结束,以选择您将遇到的最可能的问题。 它也可以以任意数量的注释或处理指令结束。 如果顶级元素没有命名为Error什么?

这是一种情况,使用字符串操作完全失败来检测:

  ...  

如果使用XmlReader处理XML,虽然它可能没有寻求EOF那么快,但它也允许您处理所有这些可能的exception情况。