C# StreamReader读取多文件时Dictionary键值丢失问题求助
问题根因
你观察到的"实例化StreamReader后Dictionary键值对丢失"是误判,问题和StreamReader本身无关,核心是代码逻辑存在漏洞导致执行中断:
- 代码里声明了局部字典
s_a暂存所有文件的解析结果,只有等全部文件读取解析完成后,才会把s_a的内容拷贝到全局字段s_c。只要读取第二个文件的过程中触发任何未捕获异常,拷贝逻辑就不会执行,你访问到的s_c永远是类初始化时的空字典,看起来就像之前存的数据丢了。 - 行解析逻辑没有做容错:遇到空行、没有分号的格式错误行时,
l_b = l_a.Split(';')返回的数组长度不足2,取l_b[0]时会直接抛出索引越界异常,刚好在第二个文件开头遇到这类行时,就会复现你说的"读到第二个文件数据就没了"的现象。 - 键存在判断用了两个独立的
if而非if/else,虽然正常流程下不会出错,但会重复做两次Key查找,属于冗余逻辑,极端场景下可能出现不可预期的问题。 double.TryParse没有判断返回值,遇到非数字的列值时会默认存入0,导致累加结果错误,但这个问题不会触发数据丢失。
修复方案
- 去掉不必要的局部字典
s_a中转,直接操作全局字段s_c,哪怕后续文件读取抛异常,已经解析完成的前序文件数据也会保留在s_c中。 - 增加行内容校验:空行、分割后列数不足、数值解析失败的异常行直接跳过,避免整个解析流程中断。
- 用
TryGetValue替代两次ContainsKey判断,减少字典查找次数提升性能,同时把两个独立if改成if/else结构消除逻辑冗余。 - 可按需增加异常捕获日志,快速定位出错的文件和具体行号。
修复后的可直接运行代码:
class TT_connect { public Dictionary<string, double> s_c = new Dictionary<string, double>(); public TT_connect(List<string> tempAS) { foreach (string a in tempAS) { using (var s = new StreamReader(a)) { while (!s.EndOfStream) { var l_a = s.ReadLine(); // 跳过空行 if (string.IsNullOrWhiteSpace(l_a)) continue; var l_b = l_a.Split(';'); // 跳过格式不符合要求的行 if (l_b.Length < 2) continue; // 数值解析失败跳过 if (!double.TryParse(l_b[1], out double parseVal)) continue; if (s_c.TryGetValue(l_b[0], out double existVal)) { s_c[l_b[0]] = existVal + parseVal; } else { s_c.Add(l_b[0], parseVal); } } } } } }
验证提示
调试时可以在每个文件读取完成的位置加断点观察字典内容,第一个文件读完时s_c已经存入对应键值对,就能确认StreamReader本身不会修改字典内容——Dictionary属于进程内托管对象,StreamReader没有任何途径访问或修改你声明的字典实例。
内容的提问来源于stack exchange,提问作者NoOneImportant
相关产品推荐
相关产品推荐

