C#序列化DataTable到文件 C#如何将DataTable保存为XML或CSV

8次阅读

datatable.writexml是最稳妥的xml导出方式,支持writeschema(保留类型和约束)与ignoreschema(仅数据);csv需手动转义字段并流式写入;json不推荐,类型信息易丢失。

C#序列化DataTable到文件 C#如何将DataTable保存为XML或CSV

DataTable.WriteXml 保存为 XML 文件最直接

直接调用 DataTable.WriteXml 是最稳妥的原生方式,它能完整保留列类型、空值、关系和约束(如果 DataTable 有 DataSet 上下文)。默认生成的是带 schema 的 XML,适合后续用 ReadXml 精确还原。

  • 写入带 schema 的完整 XML:table.WriteXml("data.xml", XmlWriteMode.WriteSchema)
  • 只写数据(更小、无类型信息):table.WriteXml("data.xml", XmlWriteMode.IgnoreSchema)
  • 如果只需要纯数据且文件要被人读,加 XmlWriteMode.WriteSchema 更安全;若仅作临时交换且双方都控制代码,IgnoreSchema 可减小体积
  • 注意:含二进制列(如 byte[])时会 Base64 编码,无需额外处理,但文件体积会明显增大

手动导出 CSV 需绕过 WriteXml 的限制

DataTable.WriteXml 不支持 CSV,必须手写导出逻辑。核心难点是字段内容含逗号、换行或双引号时的转义——不能简单用 String.Join 拼接。

  • 逐行处理,对每个字段调用 EscapeCsvField(value)(逻辑:含 ",n 就用双引号包裹,并将内部 " 替换为 ""
  • 列名行也要转义:string.Join(",", table.Columns.Cast<datacolumn>().select(c => EscapeCsvField(c.ColumnName)))</datacolumn>
  • 避免用 StreamWriter 默认编码(可能为 UTF-8 bom),显式指定 new StreamWriter("data.csv", false, Encoding.UTF8),否则 excel 打开中文可能乱码
  • 不推荐用第三方 CSV 库(如 CsvHelper)来导出简单 DataTable——引入依赖得不偿失,几行转义逻辑足够可靠

序列化成 JSON 不是 DataTable 的强项

虽然可以用 System.Text.Json 或 Newtonsoft.Json 把 DataTable 转成 JSON,但结果通常是嵌套很深的数组+对象结构,且类型信息丢失严重(所有值变字符串或数字),NULLDBNull 处理也容易出错。

  • 若真需要 JSON,先用 table.AsEnumerable().Select(r => r.ItemArray.ToDictionary(...)) 转成 List<dictionary object>></dictionary>,再序列化
  • 注意:DateTime 列默认输出为长整型 ticks,需配置 JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter()) 并自定义 JsonConverter<datetime></datetime> 才能输出 ISO 格式
  • 比起 XML/CSV,JSON 对 DataTable 属于“能用但不推荐”——除非下游明确只要 JSON 且接受数据扁平化

文件路径与异常必须显式处理

WriteXml 和手动写 CSV 都可能因权限、路径不存在或磁盘满抛出 IOExceptionUnauthorizedAccessException,.NET 不会静默吞掉这些错误。

  • 写之前检查目录是否存在:Directory.CreateDirectory(Path.GetDirectoryName(filePath))
  • 不要把 filePath 写死为相对路径(如 "data.xml"),运行时工作目录不可控;用 Path.Combine(AppContext.BaseDirectory, "data.xml") 更稳
  • CSV 导出时若某列值是 DBNull.Value,直接 .ToString() 得到空字符串,但业务上可能期望写成 "NULL" 或留空——需按需统一处理 DBNull
  • 大表(>10 万行)导出 CSV 时避免一次性拼接整个字符串,改用 StreamWriter.WriteLine 流式写入,防内存溢出

实际用的时候,XML 选 WriteXml,CSV 自己写几行转义逻辑,别贪快用正则替换引号——那个坑比想象中深。

text=ZqhQzanResources