从Xml文件加载大字符串时出现OutOfMemoryException

时间:2010-12-09 21:29:02

标签: c# xml

我正在尝试从Xml文件中加载一个非常大的字符串并将其保存到IXmlSerializable#ReadXml方法中的临时文件中,正在使用的代码如下所示。

问题是我在OutOfMemoryException行上收到了reader.ReadStartElement("data");。似乎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();
}

1 个答案:

答案 0 :(得分: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方法自己实例化XmlReader.Create。这将创建一个不预加载值并支持分块的实现。

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调用成功。