我必须解析80 GB的XML才能从该文件中获取一些数据。我为此目的使用了XML阅读器。当我用304 MB文件检查代码时。然后它在4秒内解析文件。所以我认为我将工作80 GB。但是它在一段时间后给了我异常的记忆。
我有以下代码:
static void Main(string[] args)
{
List<Test> lstTest = new List<Test>();
bool isTitle = false;
bool isText = false;
using (XmlReader Reader = XmlReader.Create(FilePath))
{
Test tt = new Test();
while (Reader.Read())
{ switch (Reader.NodeType)
{
case XmlNodeType.Element:
if (Reader.Name == "title")
{
isTitle = true;
}
if (Reader.Name == "text")
{
isText = true;
}
break;
case XmlNodeType.Text:
if (isTitle)
{
tt.Title = Reader.Value;
isTitle = false;
}
if (isText)
{
tt.Text = Reader.Value;
isText = false;
}
break;
}
if (tt.Text != null)
{
lstTest.Add(tt);
tt = new Test();
}
}
}
}
}
}
所以请建议。谢谢你的帮助。
答案 0 :(得分:6)
你是对的,XmlReader
是正确的方法。并且XmlReader
不是内存不足 - 这是你lstTest
,你可以在那里推送你找到的大多数节点。
使用XmlReader
的正确方法是处理节点,然后忘记它们,继续前进。您可以将结果写入磁盘,或者计算一些运行总计,或者其他任何 - 但不要将您在内存中读取的所有内容保留在内 - 这会使XmlReader
的目的失效。
答案 1 :(得分:3)
您不应将所有内容存储在内存中,而只保留您感兴趣的部分。
可以通过IEnumerable<>
和yield return
关键字
public IEnumerable<Test> ParseXml(string path)
{
bool isTitle = false;
bool isText = false;
using (XmlReader Reader = XmlReader.Create(FilePath))
{
Test tt = new Test();
while (Reader.Read())
{
switch (Reader.NodeType)
{
case XmlNodeType.Element:
if (Reader.Name == "title")
{
isTitle = true;
}
if (Reader.Name == "text")
{
isText = true;
}
break;
case XmlNodeType.Text:
if (isTitle)
{
tt.Title = Reader.Value;
isTitle = false;
}
if (isText)
{
tt.Text = Reader.Value;
isText = false;
}
break;
}
if (tt.Text != null)
{
yield return tt;
tt = new Test();
}
}
}
}
用法:
var data = ParseXml(/* your xml file */);
// select the part that you are interested in
var interestingTests = data
.Where(x => x.Title == "...")
foreach (var test in interestingTests)
{
// work with the interesting parts
}