I'm trying to simply load a very large string from an Xml file and save it to a temporary file inside the IXmlSerializable#ReadXml method, the code being used is below.
The problem is I'm getting an OutOfMemoryExce开发者_Go百科ption on the reader.ReadStartElement("data"); line. It appears that the XmlReader is attempting to preload the value string and as it is ~500Mb in this case it is failing to allocate a StringBuilder for it.
Is there some better way of copying this string into a file, or some way to bypass the preloading of the 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();
}
Found a solution, the problem isn't in the IXmlSerializable#ReadXml method, it's actually in the method that calls XmlSerializer#Deserialize. Originally I had this:
private void OpenSavedData(StreamReader strmReader, string fileName)
{
XmlSerializer serializer = new XmlSerializer(typeof(SavedData));
SavedData savedData = serializer.Deserialize(strmReader) as SavedData;
// Process data
}
By default Deserialize generates a XmlTextReader to pass to the ReadXml method. If I had actually made it past the ReadStartElement call I would have found that XmlTextReader doesn't support GetValueChunk.
Instead I need to instantiate an XmlReader myself using the XmlReader.Create method. This will create an implementation that doesn't preload the values and supports chunking.
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
}
This then allows the ReadXml call to succeed.
加载中,请稍侯......
精彩评论