我正在尝试从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();
}
答案 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
调用成功。