Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/EmptyTag/144.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 读取XML文件(文件大小大于500 MB)_C#_.net_Xml - Fatal编程技术网

C# 读取XML文件(文件大小大于500 MB)

C# 读取XML文件(文件大小大于500 MB),c#,.net,xml,C#,.net,Xml,我试图解析大型XML文件(大小接近600MB)并使用 这需要更长的时间,最后,整个过程被中止。进程以异常结束 消息:“线程被中止” 方法: private string ReadXml(XmlTextReader reader, string fileName) { string finalXML = ""; string s1 = ""; try { while (reader.Read()) { swit

我试图解析大型XML文件(大小接近600MB)并使用

这需要更长的时间,最后,整个过程被中止。进程以异常结束

消息:“线程被中止”

方法:

private string ReadXml(XmlTextReader reader, string fileName)
{
    string finalXML = "";
    string s1 = "";
    try
    {
        while (reader.Read())
        {
            switch (reader.NodeType)
            {
                case XmlNodeType.Element: // The node is an element.
                    s1 += "<" + reader.Name + ">";
                    break;
                case XmlNodeType.Text: //Display the text in each element.
                    s1 += reader.Value;
                    break;
                case XmlNodeType.EndElement: //Display the end of the element.
                    s1 += "</" + reader.Name + ">";
                    break;
            }
            finalXML = s1;
        }
    }
    catch (Exception ex)
    {
       Logger.Logger.LogMessage(ex, "File Processing error: " + fileName);
    }
    reader.Close();
    reader.Dispose();

    return finalXML;
}

有没有更好的方法来读取和解析大型xml文件?我需要一个建议

问题在于,正如Jon Skeet和DiskJunky所提到的,您的数据集太大,无法加载到内存中,并且您的代码没有针对处理此问题进行优化。因此,各种类都会抛出“内存不足异常”

首先,字符串连接。由于字符串的工作方式,使用多个字符串的简单连接(a+b)通常是一个坏主意。我建议在线查找如何有效处理字符串连接(例如,Jon Skeet的)

然而,这是对代码的优化,主要问题是您试图加载到内存中的XML文件的绝对大小。为了处理大型数据集,如果您可以“流化”数据,处理数据块而不是整个文件,通常会更好


由于您没有展示XML的示例,我冒昧地举了一个简单的示例来说明我的意思

假设您拥有以下XML:

<root>
   <specialelement>
      <value1>somevalue</value1>
      <value2>somevalue</value2>
   </specialelement>
   <specialelement>
      <value1>someothervalue</value1>
      <value2>someothervalue</value2>
   </specialelement>
   ... 
</root>
我假设我们可以单独处理每个
SpecialElement
,并为此定义一个处理程序,如下所示:

public void HandleElement(ExampleClass item)
{
    // Process stuff
}
现在,我们可以使用
XmlTextReader
单独读取XML中的每个元素,当我们到达
specialelement
时,我们会跟踪XML元素中包含的数据。当我们到达
specialelement
的末尾时,我们将其反序列化为一个对象,并将其发送给处理程序进行处理。例如:

using (var reader = new XmlTextReader( /* your inputstream */ ))
{
    // Buffer for the element contents
    StringBuilder sb = new StringBuilder(1000);

    // Read till next node
    while (reader.Read())
    {
        switch (reader.NodeType)
        {
            case XmlNodeType.Element: 
                // Clear the stringbuilder when we start with our element 
                if (string.Equals(reader.Name, "specialelement"))
                {
                    sb.Clear();
                }

                // Append current element without namespace
                sb.Append("<").Append(reader.Name).Append(">");
                break;

            case XmlNodeType.Text: //Display the text in each element.
                sb.Append(reader.Value);
                break;

            case XmlNodeType.EndElement: 

                // Append the closure element
                sb.Append("</").Append(reader.Name).Append(">");

                // Check if we have finished reading our element
                if (string.Equals(reader.Name, "specialelement"))
                {
                    // The stringbuilder now contains the entire 'SpecialElement' part
                    using (TextReader textReader = new StringReader(sb.ToString()))
                    {
                        // Deserialize
                        var deserializedElement = (ExampleClass)serializer.Deserialize(textReader);
                        // Send to handler
                        HandleElement(deserializedElement);
                    }
                }

                break;
        }
    }
}
使用(var reader=newXMLTextReader(/*您的inputstream*/)
{
//元素内容的缓冲区
StringBuilder sb=新StringBuilder(1000);
//读到下一个节点
while(reader.Read())
{
开关(reader.NodeType)
{
case XmlNodeType.Element:
//在开始使用元素时清除stringbuilder
if(string.Equals(reader.Name,“specialelement”))
{
(某人清楚地);
}
//附加当前元素而不带命名空间
某人加上(“”);
打破
case XmlNodeType.Text://显示每个元素中的文本。
某人附加(读者价值);
打破
案例XmlNodeType.EndElement:
//附加闭包元素
某人加上(“”);
//检查我们是否已完成元素的读取
if(string.Equals(reader.Name,“specialelement”))
{
//stringbuilder现在包含整个“SpecialElement”部分
使用(TextReader TextReader=newStringReader(sb.ToString()))
{
//反序列化
var deserializedElement=(ExampleClass)序列化程序。反序列化(textReader);
//发送给处理程序
HandleElement(反序列化删除);
}
}
打破
}
}
}
当我们开始处理来自流的数据时,我们不必将整个文件加载到内存中。保持程序的内存使用率较低(防止内存不足异常)

签出以查看它的运行情况


请注意,这是一个简单的示例,您仍有很多地方可以进一步改进和优化此代码。

正如Jon Skeet和DiskJunky所提到的,问题在于您的数据集太大,无法加载到内存中,而您的代码没有针对处理此问题进行优化。因此,各种类都会抛出“内存不足异常”

首先,字符串连接。由于字符串的工作方式,使用多个字符串的简单连接(a+b)通常是一个坏主意。我建议在线查找如何有效处理字符串连接(例如,Jon Skeet的)

然而,这是对代码的优化,主要问题是您试图加载到内存中的XML文件的绝对大小。为了处理大型数据集,如果您可以“流化”数据,处理数据块而不是整个文件,通常会更好


由于您没有展示XML的示例,我冒昧地举了一个简单的示例来说明我的意思

假设您拥有以下XML:

<root>
   <specialelement>
      <value1>somevalue</value1>
      <value2>somevalue</value2>
   </specialelement>
   <specialelement>
      <value1>someothervalue</value1>
      <value2>someothervalue</value2>
   </specialelement>
   ... 
</root>
我假设我们可以单独处理每个
SpecialElement
,并为此定义一个处理程序,如下所示:

public void HandleElement(ExampleClass item)
{
    // Process stuff
}
现在,我们可以使用
XmlTextReader
单独读取XML中的每个元素,当我们到达
specialelement
时,我们会跟踪XML元素中包含的数据。当我们到达
specialelement
的末尾时,我们将其反序列化为一个对象,并将其发送给处理程序进行处理。例如:

using (var reader = new XmlTextReader( /* your inputstream */ ))
{
    // Buffer for the element contents
    StringBuilder sb = new StringBuilder(1000);

    // Read till next node
    while (reader.Read())
    {
        switch (reader.NodeType)
        {
            case XmlNodeType.Element: 
                // Clear the stringbuilder when we start with our element 
                if (string.Equals(reader.Name, "specialelement"))
                {
                    sb.Clear();
                }

                // Append current element without namespace
                sb.Append("<").Append(reader.Name).Append(">");
                break;

            case XmlNodeType.Text: //Display the text in each element.
                sb.Append(reader.Value);
                break;

            case XmlNodeType.EndElement: 

                // Append the closure element
                sb.Append("</").Append(reader.Name).Append(">");

                // Check if we have finished reading our element
                if (string.Equals(reader.Name, "specialelement"))
                {
                    // The stringbuilder now contains the entire 'SpecialElement' part
                    using (TextReader textReader = new StringReader(sb.ToString()))
                    {
                        // Deserialize
                        var deserializedElement = (ExampleClass)serializer.Deserialize(textReader);
                        // Send to handler
                        HandleElement(deserializedElement);
                    }
                }

                break;
        }
    }
}
使用(var reader=newXMLTextReader(/*您的inputstream*/)
{
//元素内容的缓冲区
StringBuilder sb=新StringBuilder(1000);
//读到下一个节点
while(reader.Read())
{
开关(reader.NodeType)
{
case XmlNodeType.Element:
//在开始使用元素时清除stringbuilder
if(string.Equals(reader.Name,“specialelement”))
{
(某人清楚地);
}
//附加当前元素而不带命名空间
某人加上(“”);
打破
case XmlNodeType.Text://显示每个元素中的文本。
某人附加(读者价值);
打破
案例XmlNodeType.EndElement:
//追加闭包