【问题标题】:Reformat and parse huge text file in C#在 C# 中重新格式化和解析巨大的文本文件
【发布时间】:2015-04-10 06:46:49
【问题描述】:

在重新格式化后,我有一些代码可以解析文本文件。

 foreach (string file in Directory.EnumerateFiles(folderPath, "*.*"))
 {
     contents = contents + File.ReadAllText(file).Replace("&gt;", ">").Replace("&lt;", "<").Replace("&quot;", "'");
     pos = contents.LastIndexOf("</event>");
     contents = contents.Substring(0, pos + 8);
 }

 contents = "<?xml version=\"1.0\" encoding=\"utf-8\"?><root>" + contents + "</root>";

 XDocument doc = new XDocument();
 doc = XDocument.Parse(contents);

文件包含 XML 标记,但格式不正确。因此,我重新格式化并存储在字符串变量 contents 中。该字符串被加载到XDocument 对象中,该程序对小文件(7-10 MB)运行流畅。

现在,有些文件的大小超过 100MB,并且代码因内存不足异常而中断。我的代码在

处中断
contents = contents + File.ReadAllText(file).Replace("&gt;", ">").Replace("&lt;", "<").Replace("&quot;", "'");

在高效文件处理的情况下,我必须使用哪些替代方法来执行相同的操作。

【问题讨论】:

  • 有人会好奇——如果文件超过 100MB,它真的需要人工可读吗?
  • 在您当前的代码中,每个Replace 都会对一个已经很大的内存字符串进行另一个字符串分配,难怪您会耗尽内存。使用流 (StreamReader),分块处理。

标签: c# xml file parsing


【解决方案1】:

正如已经指出的那样,关键是使用流而不是完整的内存操作。

您可以创建一个自定义的TextReader 子类FormattingReader 包装StreamReader 或类似的,并在阅读时即时执行您的格式化过程:

  • 输出 XML 标头
  • 输出开头&lt;root&gt;标签
  • 遍历您的文件:
    • 当您在包装好的阅读器上看到 &amp;lt;&amp;gt; 时,改为输出尖括号
    • 当您看到&lt;/event&gt; 标记时,将其视为文件结尾
  • 输出关闭&lt;/root&gt;

然后使用采用TextReaderXmlReader.Create() 重载并传递您的FormattingReader 的实例。

【讨论】:

  • 抱歉,我错过了您使用 LastIndexOf 查找要省略的 &lt;/event&gt; 标记。因此我的算法描述不合适,这个想法可能无济于事;这取决于您需要提前多少才能确定您是否刚刚看到最后一个&lt;/event&gt;。但是我不会删除它,因为它可能仍然会给你另一个尝试的选择。
【解决方案2】:

您将无法使用 XDocument 处理超过 100 MB 的文件,因为它将所有内容都存储在内存中并在内存中执行所有操作。为此目的使用 XmlReader。

【讨论】:

  • 是的。虽然您的解析代码可能会使用一些性能改进,但它不太可能导致实际的内存不足问题。确实是 XDocument 使用对内存不敏感,因此会导致您的问题。如果您不想处理 XmlReader(它相当低级),请查看 XStreamingElement(msdn.microsoft.com/en-us/library/…msdn.microsoft.com/en-us/library/bb387013.aspx
  • 我在处理大文件时遇到了完全相同的问题,切换到 XmlReader 后,内存消耗减少了大约 10 倍,所以这是一个很好的解决方案。
  • 我的代码在 contents = contents + File.ReadAllText(file).Replace(">", ">").Replace("<", "
  • 所以在使用 XMLReader 之前,我需要找到格式化文件的解决方案
  • 重要的是不要一次阅读所有内容,也不要多次复制 100 Mb 的内容!每个替换都是 100 Mb 的副本。
猜你喜欢
  • 2023-03-15
  • 2014-08-18
  • 2012-06-07
  • 2010-10-29
  • 2023-03-19
  • 1970-01-01
  • 2020-02-12
相关资源
最近更新 更多