簡體   English   中英

讀取XML文件(文件大小> 500 MB)

[英]Reading XML File ( File size > 500 MB)

我正在嘗試解析大型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;
}

然后閱讀和脫鹽:

string finalXML = string.Empty;
XmlTextReader reader = new XmlTextReader(unzipfile);
finalXML = await ReadXml(reader, fileName);

var xmlremovenamespae = Helper.RemoveAllNamespaces(finalXML);
XmlParseObjectNew.BizData myxml = new XmlParseObjectNew.BizData();

using (StringReader sr = new StringReader(xmlremovenamespae))
 {
       XmlSerializer serializer = new XmlSerializer(typeof(XmlParseObjectNew.BizData));
       myxml = (XmlParseObjectNew.BizData)serializer.Deserialize(sr);
 }

有沒有更好的方法來讀取和解析大型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>

這個XML的要解析specialelement為對象,用下面的類定義:

[XmlRoot("specialelement")]
public class ExampleClass
{
    [XmlElement(ElementName = "value1")]
    public string Value1 { get; set; }    
    [XmlElement(ElementName = "value2")]
    public string Value2 { get; set; }
}

我假設我們可以分別處理每個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;
        }
    }
}

當我們開始處理流中的數據時,我們不必將整個文件加載到內存中。 保持程序的內存使用率較低(防止內存不足異常)。

查看這個小提琴 ,看看它的實際效果。

請注意,這是一個快速示例,仍然有很多地方可以進一步改進和優化此代碼。

我嘗試這個並且工作正常。

fileName =“您的文件路徑”;

試試這個代碼,它可以在幾秒鍾內解析出大於500MB的XML文件。

using (TextReader textReader = new StreamReader(fileName))
  {
    using (XmlTextReader reader = new XmlTextReader(textReader))
      {                                   
       reader.Namespaces = false;
 XmlSerializer serializer = new XmlSerializer(typeof("YourXmlClassType"));
          parseData = ("YourXmlClassType")serializer.Deserialize(reader);
      }
  }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM