如何优化9500行量级的JSON与DataTable处理代码?能否免foreach遍历?
代码优化方案与问题解答
关于"无需foreach遍历直接获取所需对象"的问题
allowedItemIds是集合类型的JSON字段,每个元素都需要单独匹配DataTable行并生成输出文本,无法完全跳过遍历——因为必须处理集合中的每一个元素。不过可以通过强类型反序列化直接获取目标对象,同时用更简洁的方式替代显式foreach(比如LINQ),优化整体逻辑。
核心优化措施(针对9500行数据的性能与简洁性)
1. 替换dynamic为强类型反序列化
用强类型模型替代dynamic,既能直接获取所需的allowedItemIds和responseId对象,又能避免动态解析的性能损耗,同时保证类型安全。
// 定义与JSON结构匹配的强类型模型 public class ResponseData { [JsonProperty("allowedItemIds")] // 对应JSON中的字段名 public List<int> AllowedItemIds { get; set; } [JsonProperty("responseId")] public string ResponseId { get; set; } } // 反序列化JSON,直接获取目标对象 var responseData = JsonConvert.DeserializeObject<ResponseData>(response.Content); var allowedItemIds = responseData.AllowedItemIds; var responseId = responseData.ResponseId;
2. 优化文件写入逻辑(大幅提升IO性能)
原代码中File.AppendAllText会在每次循环中打开、写入、关闭文件,9500次操作会产生巨大的IO开销。改用批量写入方式:
方式一:StreamWriter批量写入
dt.PrimaryKey = new[] { dt.Columns["number"] }; using (var writer = new StreamWriter(newFileName, append: true)) { foreach (var allowedItem in allowedItemIds) { var drw = dt.Rows.Find(allowedItem); if (drw == null) continue; // 避免找不到行时的空引用异常 // 用列名访问DataRow,替代ItemArray索引,提升可读性 var number = drw["number"]?.ToString(); var surname = drw["surname"]?.ToString(); var forename = drw["forename"]?.ToString(); var emailAddress = drw["emailAddress"]?.ToString(); // 字符串插值替代拼接,代码更简洁 var clientDetails = $" {number},\"{surname}\",\"{forename}\",\"{emailAddress}\",\"{responseId}\",\"{daytime}\""; writer.WriteLine(clientDetails); } }
方式二:LINQ+File.AppendAllLines(更简洁的写法)
用LINQ简化遍历逻辑,File.AppendAllLines会一次性写入所有行:
dt.PrimaryKey = new[] { dt.Columns["number"] }; var outputLines = allowedItemIds .Select(itemId => dt.Rows.Find(itemId)) .Where(row => row != null) // 过滤不存在的行 .Select(row => $" {row["number"]?.ToString()},\"{row["surname"]?.ToString()}\",\"{row["forename"]?.ToString()}\",\"{row["emailAddress"]?.ToString()}\",\"{responseId}\",\"{daytime}\""); File.AppendAllLines(newFileName, outputLines);
3. 其他细节优化
- 移除无用变量:原代码中
resp变量未被使用,直接删除。 - 增加空值判断:添加
if (drw == null) continue;处理DataTable中找不到对应ID的情况,避免空引用异常。 - 用列名访问DataRow:替代
ItemArray[index],代码更易维护,后续列顺序变化不会引发错误。
优化后的效果
- 性能:IO操作从9500次减少到1次,强类型反序列化比
dynamic更高效,整体处理速度大幅提升。 - 简洁性:代码结构清晰,类型安全,可读性和可维护性显著提高。
内容的提问来源于stack exchange,提问作者Ace2874
相关产品推荐
相关产品推荐

