当你创建一个新XDocument
使用XDocument.Load
,它打开XML文件,并保持一个本地副本,或者它连续读取从硬盘驱动器的文件? 如果它连续读取,是有解析XML更快的方法?
XDocument x = XDocument.Load("file.xml");
当你创建一个新XDocument
使用XDocument.Load
,它打开XML文件,并保持一个本地副本,或者它连续读取从硬盘驱动器的文件? 如果它连续读取,是有解析XML更快的方法?
XDocument x = XDocument.Load("file.xml");
有一对夫妇的测量结果来考虑:
为了回答眼前的问题: XDocument
使用一个XmlReader
通过读取每个元素和创建对应于将文档装入存储器XElement
实例(见下文代码)。 因此,它应该是相当快(快足以满足大多数的目的),但分析大量文件时,它可能会消耗大量的内存。
原始XmlReader
是,如果您的需求仅限于对于遍历一个很好的选择,可以不保留在内存中的文件来完成。 因为没有创建显著结构,也不符合与其他节点解析(如连接父和子节点),它的表现将优于其他方法。 然而,按需查询能力几乎是不存在的; 您可以反应在每个节点中找到的值,但不能查询文档作为一个整体。 如果您需要查看该文档的第二次,你必须再次遍历整个事情。
相比之下,一个XDocument
将需要更长的时间来遍历,因为它实例化新对象,并执行基本结构的任务。 它也将消耗内存相称源的大小。 为了换取这些权衡,您将获得出色的查询能力。
这可能是可行的,因为方法结合起来, 通过乔恩斯基特提到这里所示: 洒进的LINQ to XML使用C#自定义迭代器和XmlReader中 。
源的XDocument负荷()
public static XDocument Load(Stream stream, LoadOptions options)
{
XmlReaderSettings xmlReaderSettings = XNode.GetXmlReaderSettings(options);
XDocument result;
using (XmlReader xmlReader = XmlReader.Create(stream, xmlReaderSettings))
{
result = XDocument.Load(xmlReader, options);
}
return result;
}
// which calls...
public static XDocument Load(XmlReader reader, LoadOptions options)
{
if (reader == null)
{
throw new ArgumentNullException("reader");
}
if (reader.ReadState == ReadState.Initial)
{
reader.Read();
}
XDocument xDocument = new XDocument();
if ((options & LoadOptions.SetBaseUri) != LoadOptions.None)
{
string baseURI = reader.BaseURI;
if (baseURI != null && baseURI.Length != 0)
{
xDocument.SetBaseUri(baseURI);
}
}
if ((options & LoadOptions.SetLineInfo) != LoadOptions.None)
{
IXmlLineInfo xmlLineInfo = reader as IXmlLineInfo;
if (xmlLineInfo != null && xmlLineInfo.HasLineInfo())
{
xDocument.SetLineInfo(xmlLineInfo.LineNumber, xmlLineInfo.LinePosition);
}
}
if (reader.NodeType == XmlNodeType.XmlDeclaration)
{
xDocument.Declaration = new XDeclaration(reader);
}
xDocument.ReadContentFrom(reader, options);
if (!reader.EOF)
{
throw new InvalidOperationException(Res.GetString("InvalidOperation_ExpectedEndOfFile"));
}
if (xDocument.Root == null)
{
throw new InvalidOperationException(Res.GetString("InvalidOperation_MissingRoot"));
}
return xDocument;
}
// which calls...
internal void ReadContentFrom(XmlReader r, LoadOptions o)
{
if ((o & (LoadOptions.SetBaseUri | LoadOptions.SetLineInfo)) == LoadOptions.None)
{
this.ReadContentFrom(r);
return;
}
if (r.ReadState != ReadState.Interactive)
{
throw new InvalidOperationException(Res.GetString("InvalidOperation_ExpectedInteractive"));
}
XContainer xContainer = this;
XNode xNode = null;
NamespaceCache namespaceCache = default(NamespaceCache);
NamespaceCache namespaceCache2 = default(NamespaceCache);
string text = ((o & LoadOptions.SetBaseUri) != LoadOptions.None) ? r.BaseURI : null;
IXmlLineInfo xmlLineInfo = ((o & LoadOptions.SetLineInfo) != LoadOptions.None) ? (r as IXmlLineInfo) : null;
while (true)
{
string baseURI = r.BaseURI;
switch (r.NodeType)
{
case XmlNodeType.Element:
{
XElement xElement = new XElement(namespaceCache.Get(r.NamespaceURI).GetName(r.LocalName));
if (text != null && text != baseURI)
{
xElement.SetBaseUri(baseURI);
}
if (xmlLineInfo != null && xmlLineInfo.HasLineInfo())
{
xElement.SetLineInfo(xmlLineInfo.LineNumber, xmlLineInfo.LinePosition);
}
if (r.MoveToFirstAttribute())
{
do
{
XAttribute xAttribute = new XAttribute(namespaceCache2.Get((r.Prefix.Length == 0) ? string.Empty : r.NamespaceURI).GetName(r.LocalName), r.Value);
if (xmlLineInfo != null && xmlLineInfo.HasLineInfo())
{
xAttribute.SetLineInfo(xmlLineInfo.LineNumber, xmlLineInfo.LinePosition);
}
xElement.AppendAttributeSkipNotify(xAttribute);
}
while (r.MoveToNextAttribute());
r.MoveToElement();
}
xContainer.AddNodeSkipNotify(xElement);
if (r.IsEmptyElement)
{
goto IL_30A;
}
xContainer = xElement;
if (text != null)
{
text = baseURI;
goto IL_30A;
}
goto IL_30A;
}
case XmlNodeType.Text:
case XmlNodeType.Whitespace:
case XmlNodeType.SignificantWhitespace:
if ((text != null && text != baseURI) || (xmlLineInfo != null && xmlLineInfo.HasLineInfo()))
{
xNode = new XText(r.Value);
goto IL_30A;
}
xContainer.AddStringSkipNotify(r.Value);
goto IL_30A;
case XmlNodeType.CDATA:
xNode = new XCData(r.Value);
goto IL_30A;
case XmlNodeType.EntityReference:
if (!r.CanResolveEntity)
{
goto Block_25;
}
r.ResolveEntity();
goto IL_30A;
case XmlNodeType.ProcessingInstruction:
xNode = new XProcessingInstruction(r.Name, r.Value);
goto IL_30A;
case XmlNodeType.Comment:
xNode = new XComment(r.Value);
goto IL_30A;
case XmlNodeType.DocumentType:
xNode = new XDocumentType(r.LocalName, r.GetAttribute("PUBLIC"), r.GetAttribute("SYSTEM"), r.Value, r.DtdInfo);
goto IL_30A;
case XmlNodeType.EndElement:
{
if (xContainer.content == null)
{
xContainer.content = string.Empty;
}
XElement xElement2 = xContainer as XElement;
if (xElement2 != null && xmlLineInfo != null && xmlLineInfo.HasLineInfo())
{
xElement2.SetEndElementLineInfo(xmlLineInfo.LineNumber, xmlLineInfo.LinePosition);
}
if (xContainer == this)
{
return;
}
if (text != null && xContainer.HasBaseUri)
{
text = xContainer.parent.BaseUri;
}
xContainer = xContainer.parent;
goto IL_30A;
}
case XmlNodeType.EndEntity:
goto IL_30A;
}
break;
IL_30A:
if (xNode != null)
{
if (text != null && text != baseURI)
{
xNode.SetBaseUri(baseURI);
}
if (xmlLineInfo != null && xmlLineInfo.HasLineInfo())
{
xNode.SetLineInfo(xmlLineInfo.LineNumber, xmlLineInfo.LinePosition);
}
xContainer.AddNodeSkipNotify(xNode);
xNode = null;
}
if (!r.Read())
{
return;
}
}
goto IL_2E1;
Block_25:
throw new InvalidOperationException(Res.GetString("InvalidOperation_UnresolvedEntityReference"));
IL_2E1:
throw new InvalidOperationException(Res.GetString("InvalidOperation_UnexpectedNodeType", new object[]
{
r.NodeType
}));
}
它将分析输入的数据流(无论是从一个文件或字符串无所谓)当你调用Load()
然后保存文档的本地实例在内存中。 由于源可以是任何东西(可能是的NetworkStream,一个DataReader,由用户输入的字符串),它不能回去,并尝试再次读取数据,因为它不知道它的状态(流被关闭等)。
如果你真的想在另一方面速度的XDocument不是fastets(全部虽然它是比较容易的工作),因为它需要先解析文档,然后在内存中保留。 如果您在使用与做法真正的大文件的工作System.Xml.XmlReader通常的方式更快,因为它可以读取文件作为流,并不需要保留除了当前元素任何东西。 这个基准测试显示有关这一些有趣的数字。
我不认为它不断地读取; 有关的好处XDocument.Load
方法是,它使用XmlReader
读取XML转换为XML树。 而且,由于现在刚创建这是最有可能保存在你的记忆是一棵树它不再不断读取文档的树。 它操纵树,因为它是树中的所有你的阅读和修改都做了很多更快。 虽然它不没有实现IDisposable
会自动配置。