我正在为两个 CSV 文件编写一个比较器脚本,其中每个新行上都有列和每列的相应值。列在文件的第一行指定。之后的每一行都包含每列的数据。文件以分号分隔。
我正在尝试创建一个程序,该程序可以处理具有不同行号和列数的文件,并且还可以显示不同值的行号,然后创建一个新的文本文件,显示行号、列名和文件 1 和文件 2 的值。
比较应该基于一些标识符而不是逐行进行。如果列行中指定的某些列数据丢失,那么它可以显示丢失数据的列数。
举个例子:
worker1.csv:
姓名 | 年龄 | 高度 | 性别 |
---|---|---|---|
鲍勃 | 21 | 190 | 男 |
约翰 | 35 | 182 | 男 |
玫瑰 | |||
玛丽 | 20 | 175 | 女 |
worker2.csv
姓名 | 年龄 | 高度 | 性别 |
---|---|---|---|
鲍勃 | 21 | 185 | 男 |
约翰 | 30 | 186 | 男 |
玛丽 |
输出.csv
Differences found in Mary:
File 2, Line number 3, Missing three values
Differences found in Bob:
File 1, Line number 1, Height: 190
File 2, Line number 1, Height: 185
Differences found in John:
File 1, Line number 2, Age: 35, Height: 182
File 2, Line number 3, Age: 30, Height: 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
}