2010-12-09 105 views
0

我試圖簡單地從Xml文件加載一個非常大的字符串並將其保存到IXmlSerializable#ReadXml方法中的臨時文件中,正在使用的代碼如下所示。從Xml文件加載大字符串時出現OutOfMemoryException

問題是我在reader.ReadStartElement("data");行上得到了OutOfMemoryException。看起來XmlReader正在嘗試預加載值字符串,因爲它在這種情況下約爲500Mb,因此它無法爲其分配StringBuilder

是否有一些更好的方法將此字符串複製到文件中,或以某種方式繞過XmlReader的預加載?

public void ReadXml(XmlReader reader) 
{ 
    // Read other elements 

    reader.ReadStartElement("data"); 

    this.dataFile = Path.GetTempFileName(); 
    FileStream tempFile = File.Create(this.dataFile); 

    char[] buffer = new char[CHUNK_SIZE]; 
    int count; 

    using (StreamWriter writer = new StreamWriter(tempFile)) 
    { 
     while ((count = reader.ReadValueChunk(buffer, 0, CHUNK_SIZE)) != 0) 
     { 
      writer.Write(buffer, 0, count); 
     } 
    } 
    reader.ReadEndElement(); 
} 
+2

ouch;這是...棘手。我認爲現在已經遲到了,可能xml不是500Mb機箱的正確格式? – 2010-12-09 21:34:14

回答

2

找到了解決方案,這個問題是不是在IXmlSerializable#ReadXml方法,它實際上是在調用XmlSerializer#Deserialize方法。本來我有這個:

private void OpenSavedData(StreamReader strmReader, string fileName) 
{ 
    XmlSerializer serializer = new XmlSerializer(typeof(SavedData)); 
    SavedData savedData = serializer.Deserialize(strmReader) as SavedData; 

    // Process data 
} 

默認情況下Deserialize生成XmlTextReader傳遞給ReadXml方法。如果我實際上已經通過ReadStartElement,我會發現XmlTextReader不支持GetValueChunk

相反,我需要使用XmlReader.Create方法實例化我自己的XmlReader。這將創建一個不預裝值並支持分塊的實現。

private void OpenSavedData(StreamReader strmReader, string fileName) 
{ 
    XmlSerializer serializer = new XmlSerializer(typeof(SavedData)); 

    XmlReaderSettings settings = new XmlReaderSettings(); 
    settings.CloseInput = true; 
    settings.IgnoreWhitespace = true; 

    SavedData savedData = null; 

    using (XmlReader xmlReader = XmlReader.Create(strmReader, settings)) 
    { 
     savedData = serializer.Deserialize(xmlReader) as SavedData; 
    } 

    // Process data 
} 

然後這允許ReadXml調用成功。

相關問題