You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C#写入OSM(XML)遇System.OutOfMemoryException的解决咨询

解决方案:使用流式XML写入替代DOM方式

你的问题根源在于XmlDocument是基于DOM的API,会将整个XML文档的所有节点加载到内存中。当osmNodes数量庞大时,x86平台的内存限制(最大约2GB可用内存)无法容纳整个DOM树,从而抛出OutOfMemoryException。

改用XmlWriter(流式XML写入API)可以彻底解决这个问题,它不需要在内存中保留整个文档结构,而是边写边输出到文件/流,内存占用极低。

替换后的实现代码

// 配置XmlWriter的输出格式,匹配你的预期XML样式
var writerSettings = new XmlWriterSettings
{
    Indent = true,
    IndentChars = "  ", // 对应预期的缩进
    Encoding = Encoding.UTF8,
    OmitXmlDeclaration = false // 如果不需要XML声明(<?xml ...?>),可以设为true
};

// 直接写入到目标文件,也可以替换为MemoryStream等其他流
using (XmlWriter writer = XmlWriter.Create("output.osm", writerSettings))
{
    writer.WriteStartDocument();
    
    // 写入根元素<osm>及属性
    writer.WriteStartElement("osm");
    writer.WriteAttributeString("version", "0.6");
    writer.WriteAttributeString("upload", "false"); // 匹配预期输出的upload属性
    
    // 循环写入每个<node>元素
    foreach (var item in osmNodes)
    {
        writer.WriteStartElement("node");
        writer.WriteAttributeString("id", item.Id.ToString());
        writer.WriteAttributeString("lat", item.Lat.ToString());
        writer.WriteAttributeString("lon", item.Lon.ToString());
        writer.WriteEndElement(); // 闭合当前<node>标签
    }
    
    writer.WriteEndElement(); // 闭合<osm>标签
    writer.WriteEndDocument();
}

为什么这个方法有效?

  • XmlWriter是向前只读的流式写入工具,每次仅处理当前要写入的元素,写完就释放相关内存,不会在内存中存储整个XML结构。
  • 无论osmNodes包含多少元素,内存占用都维持在很小的固定范围内,完全适配x86/AnyCPU平台的内存限制。

备选方案(若必须使用XmlDocument)

如果因为业务需求必须保留DOM操作,可以采用分批写入的方式:

  1. 每次处理一部分osmNodes(比如每1000个为一批),添加到osmElement后将文档保存到临时文件。
  2. 清空XmlDocument和osmElement,释放内存,再处理下一批。
  3. 最后将所有临时文件合并为最终的OSM文件。

不过这种方案复杂度高、效率低,优先推荐使用XmlWriter的流式写入方案。

内容的提问来源于stack exchange,提问作者Vinayak Pattar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 22:41:34