XmlReader 是 C# 中高效流式解析大型 XML 的首选,逐节点而非逐行读取,需用 XmlReader.Create() 配合 XmlReaderSettings(如 IgnoreWhitespace、DtdProcessing.Ignore)配置,通过 Read() 和 NodeType 判断驱动循环,边读边处理、及时释放资源。

XmlReader 是 C# 中高效读取大型 XML 文件的首选方式,它采用流式(SAX 风格)解析,不加载整个文档到内存,适合处理 GB 级 XML。关键不是“逐行”,而是“逐节点”——XML 没有严格意义上的“行”概念,但你可以按元素、属性、文本等粒度精准控制读取。
用 XmlReader.Create() 创建轻量读取器
避免直接 new XmlReader(),用静态工厂方法创建,并可传入配置:
- 设置 XmlReaderSettings 控制是否忽略空白、是否校验 DTD、是否展开实体等
- 对超大文件,建议关闭 DTD 处理(
settings.DtdProcessing = DtdProcessing.Ignore)防止外部实体攻击或意外网络请求 - 示例:var settings = new XmlReaderSettings {IgnoreWhitespace = true, DtdProcessing = DtdProcessing.Ignore};
用 Read() + 节点类型判断驱动循环
核心是调用 Read() 方法前进到下一个节点,再用 NodeType 和 Name 判断当前是什么内容:
- XmlNodeType.Element:遇到开始标签,如
<book></book>;可用reader.GetAttribute("id")读属性 - XmlNodeType.Text:读取元素内的纯文本内容(注意:需先 Read() 到该节点)
- XmlNodeType.EndElement:遇到结束标签,如
,常用于配对逻辑或清理 - 跳过注释、处理指令等干扰项:检查
reader.NodeType != XmlNodeType.Comment
按需提取数据,避免缓存整棵树
不要把所有节点存进 List 或 XElement;而是边读边处理:
- 遇到目标元素(如
<order></order>),立刻新建临时对象,用 while 循环读其子节点填充字段 - 读完一个完整业务单元(如一个订单),立即入库、写日志或发送消息,然后丢弃引用
- 若需 XPath 定位,XmlReader 不支持;此时应改用 XDocument.Load(reader)(仅限小片段)或结合 XmlReader.ReadSubtree() 提取子树
别忘了异常处理和资源释放
XmlReader 可能因格式错误抛出 XmlException,且必须显式释放:
- 用 using 语句确保 Close() 被调用,即使发生异常
- 捕获 XmlException 并记录行号(
e.LineNumber)和位置(e.LinePosition),方便定位坏数据 - 示例:using var reader = XmlReader.Create(“data.xml”, settings);
基本上就这些。不用加载全量 DOM,靠状态机式推进,配合清晰的节点类型分支,就能稳稳吃下几个 GB 的 XML。不复杂但容易忽略细节,比如空白处理和 DTD 关闭——这两点往往是大文件解析失败的隐形原因。