我正在为两个具有列和相应值的 csv 文件做比较器对于每个新行上的每一列。列在文件的第一行指定。之后的每一行都包含每列的数据。
我正在尝试创建一个程序,该程序可以处理具有不同行号和列数的文件,并且还可以显示不同值的行号,然后创建一个新的文本文件,显示行号,列名和文件1和文件2的值。
比较应基于某些标识符而不是逐行进行比较。如果缺少列行中指定的某些列数据,则它可以显示缺少数据的列数。
所以例如:
工人1.csv:
名字;年龄;高度;性;
鲍勃;21;190;雄
约翰福音;35;182;雄
玫;
玛丽;20;175;女性
工人2.csv
名字;年龄;高度;性
鲍勃;21;185;雄
约翰福音;30;186;雄
玛丽;
输出.csv
在玛丽身上发现的差异:
文件 2,第 3 行,缺少三个值
在鲍勃中发现的差异:
文件 1,第 1 行,高度:190
文件 2,第 1 行,高度:185
在约翰身上发现的差异:
文件 1,第 2 行,年龄:35,身高:182
文件 2,第 3 行,年龄:30,身高:186
我应该怎么做?我确实在两个文件行上查看了 LINQ 的 Except ,但我如何获取行号?
这比它第一次出现时要复杂一些。但如果你一步一步地接近它,它是可行的。
我假设您有足够的内存将文件的一条记录加载到字典中。如果您的文件非常大,事情就会变得更加复杂。
您要做的第一件事是将其中一个文件加载到字典中,按 ID 编制索引。在我的示例中,我将假定 ID 是名称。每条记录将记录在FileLine
实例中:
class FileLine
{
public int LineNumber;
public string Name;
public int Age;
public int Height;
public string Gender;
}
还有你的字典:
Dictionary<string, FileLine> File1Lines = new Dictionary<string, FileLine>();
现在,将文件读入该字典:
int lineNumber = 0;
foreach (var line in File.ReadLines("worker1.csv")
{
// split the line and assign the fields.
// End up with name, age, height, and gender variables.
++lineNumber;
var theLine = new FileLine(
LineNumber = lineNumber,
Name = name,
Age = age,
Height = height,
Gender = gender);
File1Lines.Add(theLine.Name, theLine);
}
现在,您可以读取第二个文件,在字典中查找该项目,并报告任何差异:
lineNumber = 0;
foreach (var line in File.ReadLines("worker2.csv"))
{
// split the line and create a FileLine instance.
// we'll call it line2
// Then, look to see if that line is in the File1Lines dictionary.
FileLine line1;
if (!File1Lines.TryGetValue(line2.Name, out line1))
{
// the line didn't exist in the first file
}
else
{
// Now compare individual fields
if (line2.Age != line1.Age)
{
// report that fields are different
}
// Do the same with other fields
}
}
现在,如果要跟踪第一个文件中的行,但不在第二个文件中,请创建一个HashSet<string>
,每当在第二个文件中找到记录时,请将名称添加到哈希集中。完成第二个文件后,您可以将哈希集与字典中的键进行比较。因此,如果您的哈希集称为 FoundRecords
,那么您将拥有:
var recordsNotFound = File1Lines.Keys.Except(FoundRecords);
foreach (var name in recordsNotFound)
{
// look up item in the dictionary to report not found
}
从两个foreach循环中,你可以找到区别,或者使用for循环也可以:
string[] content1 = File.ReadAllLines(@"worker1.csv");
string[] content2 = File.ReadAllLines(@"worker2.csv");
for(int i = 0; i < content1.Length; i++)
{
// check here every line, i is your line number
}
for(int i = 0; i < content2.Length; i++)
{
// check here every line, i is your line number
}