C#异常处理继续发生错误
时间:2020-03-06 14:43:49 来源:igfitidea点击:
我有一个基本的Cconsole应用程序,它逐行读取文本文件(CSV格式)并将数据放入HashTable中。该行中的第一个CSV项是键(编号num),其余部分是值。但是,我发现导入文件中有一些本不应该的重复键。当我尝试导入文件时,应用程序会出错,因为HashTable中不能有重复的键。我希望我的程序能够处理此错误。当我遇到重复的键时,我想将该键放入arraylist中,然后继续将其余数据导入哈希表中。我该如何在C#中做到这一点
这是我的代码:
私有静态Hashtable importFile(Hashtable myHashtable,String myFileName)
{
StreamReader sr = new StreamReader(myFileName); CSVReader csvReader = new CSVReader(); ArrayList tempArray = new ArrayList(); int count = 0; while (!sr.EndOfStream) { String temp = sr.ReadLine(); if (temp.StartsWith(" ")) { ServMissing.Add(temp); } else { tempArray = csvReader.CSVParser(temp); Boolean first = true; String key = ""; String value = ""; foreach (String x in tempArray) { if (first) { key = x; first = false; } else { value += x + ","; } } myHashtable.Add(key, value); } count++; } Console.WriteLine("Import Count: " + count); return myHashtable; }
解决方案
更好的解决方案是调用ContainsKey来检查键是否存在,然后再将其添加到哈希表中。在这种错误上抛出异常会影响性能,并不能改善程序流程。
if (myHashtable.ContainsKey(key)) duplicates.Add(key); else myHashtable.Add(key, value);
ContainsKey的每个项目都有恒定的O(1)开销,而捕获异常会导致重复项目的性能下降。
在大多数情况下,我会说要检查密钥,但是在这种情况下,最好捕获异常。
这是一个解决方案,它避免了次要列表中的多次匹配,而对所有插入操作的开销却很小:
Dictionary<T, List<K>> dict = new Dictionary<T, List<K>>(); //Insert item if (!dict.ContainsKey(key)) dict[key] = new List<string>(); dict[key].Add(value);
我们可以将字典包装为隐藏该类型的字典,也可以将其放入字典的方法甚至扩展方法中。
谢谢你们。
我最终使用了ContainsKey()方法。这可能需要30秒以上的时间,这对我来说是很好的。我正在加载大约170万行,该程序总共花费大约7分钟来加载两个文件,进行比较并写出几个文件。比较和写出文件只需要2秒钟。
如果我们有4个以上(例如)CSV值,则可能值得将value变量设置为也使用StringBuilder,因为字符串连接是一个缓慢的函数。
嗯,一百七十万行?我很乐意为此类负载提供此服务。
这是使用LINQ做到这一点的一种方法。
CSVReader csvReader = new CSVReader(); List<string> source = new List<string>(); using(StreamReader sr = new StreamReader(myFileName)) { while (!sr.EndOfStream) { source.Add(sr.ReadLine()); } } List<string> ServMissing = source .Where(s => s.StartsWith(" ") .ToList(); //-------------------------------------------------- List<IGrouping<string, string>> groupedSource = ( from s in source where !s.StartsWith(" ") let parsed = csvReader.CSVParser(s) where parsed.Any() let first = parsed.First() let rest = String.Join( "," , parsed.Skip(1).ToArray()) select new {first, rest} ) .GroupBy(x => x.first, x => x.rest) //GroupBy(keySelector, elementSelector) .ToList() //-------------------------------------------------- List<string> myExtras = new List<string>(); foreach(IGrouping<string, string> g in groupedSource) { myHashTable.Add(g.Key, g.First()); if (g.Skip(1).Any()) { myExtras.Add(g.Key); } }