You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C#中基于Hashtable实现两个CSV文件AccessDetails对比的问题

问题描述

现有两个CSV文件,均包含EmployeeId、Username等字段,其中AccessDetails字段格式为CardNumber|SecretPin|TokenNumber。需按以下规则对比处理:

  • 卡号匹配但Token不匹配:不处理
  • 卡号不匹配但Token匹配:不处理
  • AccessDetails为NULL时:将员工详情输出至其他文件
  • 卡号和Token均不匹配时:将员工详情输出至其他文件

当前采用Hashtable存储文件内容,以cardnumber为键,仅能实现第一条规则,无法处理卡号不同但Token相同的情况,也不知道如何处理AccessDetails为NULL的无关联记录。考虑将键设为cardnumber+tokennumber,但不知道如何在键中单独检索卡号或Token,寻求解决方案。

现有存储File1的代码:

if (!_File1.ContainsKey(cardnumber))
 _File1.Add(cardnumber, username + "," + branchId + "," + employeeID + "," + cardnumber + "," + tokennumber + "," + empType + "," + newJoinee);

读取File2并对比的代码:

//readingFile2 data
row = SplitCSV(line);

employeeID = row[employeeIndex].Trim().ToString();
username = row[UsernameIndex].Trim().ToString();
branchID = row[branchIdIndex].Trim().ToString();
newJoinee = row[njIndex].Trim().ToString();
emptype = row[emptypeIdIndex].Trim().ToString();
accessdetails = row[ValueIndex].Trim().ToString();

if (!accessdetails.Equals("NULL"))
{
    string[] values = value.Split('|');
    cardnumberfile2 = values[0];
    tokenumberFile2 = values[2];
}
else
{
    cardnumberfile2 = employeeID;
    tokennumberfile2 = "";
}

if(_file1.ContainsKey(cardnumberfile2))
{
   //reading values from File1
  
   // As cardnumber in file2 is present in the file1, then do nothing
}
解决方案

1. 放弃Hashtable,改用强类型存储+双索引字典

用cardnumber+tokennumber当键没法单独检索卡号或Token,不如定义一个员工信息类,同时维护两个字典:

  • 以CardNumber为键,存储对应员工信息列表(兼容同卡号不同Token的场景)
  • 以TokenNumber为键,存储对应员工信息列表

步骤1:定义员工信息类

public class EmployeeInfo
{
    public string Username { get; set; }
    public string BranchId { get; set; }
    public string EmployeeId { get; set; }
    public string CardNumber { get; set; }
    public string TokenNumber { get; set; }
    public string EmpType { get; set; }
    public string NewJoinee { get; set; }

    // 快速转成CSV行的方法
    public string ToCsvLine()
    {
        return $"{Username},{BranchId},{EmployeeId},{CardNumber},{TokenNumber},{EmpType},{NewJoinee}";
    }
}

步骤2:重构File1的存储逻辑

替换Hashtable为两个字典:

// 按卡号分组存储
Dictionary<string, List<EmployeeInfo>> _file1ByCard = new Dictionary<string, List<EmployeeInfo>>();
// 按Token分组存储
Dictionary<string, List<EmployeeInfo>> _file1ByToken = new Dictionary<string, List<EmployeeInfo>>();

// 存储File1数据时
EmployeeInfo empInfo = new EmployeeInfo
{
    Username = username,
    BranchId = branchId,
    EmployeeId = employeeID,
    CardNumber = cardnumber,
    TokenNumber = tokennumber,
    EmpType = empType,
    NewJoinee = newJoinee
};

// 添加到卡号字典
if (!_file1ByCard.ContainsKey(cardnumber))
{
    _file1ByCard[cardnumber] = new List<EmployeeInfo>();
}
_file1ByCard[cardnumber].Add(empInfo);

// 添加到Token字典(统一处理空Token场景)
string tokenKey = string.IsNullOrEmpty(tokennumber) ? string.Empty : tokennumber;
if (!_file1ByToken.ContainsKey(tokenKey))
{
    _file1ByToken[tokenKey] = new List<EmployeeInfo>();
}
_file1ByToken[tokenKey].Add(empInfo);

2. 重构File2的对比处理逻辑

步骤1:优先处理AccessDetails为NULL的情况

直接写入目标文件,跳过后续对比:

if (accessdetails.Equals("NULL", StringComparison.OrdinalIgnoreCase))
{
    // 构造CSV行并写入文件
    string outputLine = $"{username},{branchID},{employeeID},,,{emptype},{newJoinee}";
    File.AppendAllText("NullAccessDetails.csv", outputLine + Environment.NewLine);
    continue;
}

步骤2:解析AccessDetails并执行规则判断

string[] values = accessdetails.Split('|');
string cardFile2 = values[0].Trim();
string tokenFile2 = values[2].Trim();

// 检查是否存在匹配的卡号/Token
bool hasMatchingCard = _file1ByCard.ContainsKey(cardFile2);
bool hasMatchingToken = _file1ByToken.ContainsKey(tokenFile2);

// 按规则分支处理
if (hasMatchingCard && !hasMatchingToken)
{
    // 规则1:卡号匹配Token不匹配,不处理
    continue;
}
else if (!hasMatchingCard && hasMatchingToken)
{
    // 规则2:卡号不匹配Token匹配,不处理
    continue;
}
else if (!hasMatchingCard && !hasMatchingToken)
{
    // 规则4:卡号和Token都不匹配,写入目标文件
    string outputLine = $"{username},{branchID},{employeeID},{cardFile2},{tokenFile2},{emptype},{newJoinee}";
    File.AppendAllText("MismatchedRecords.csv", outputLine + Environment.NewLine);
}
// 剩余场景:卡号和Token都匹配,不处理

3. 额外注意事项

  • 字符串比较用StringComparison.OrdinalIgnoreCase避免大小写问题
  • 空Token统一用空字符串作为键,避免索引混乱
  • 数据量大时建议用StreamWriter批量写入文件,比File.AppendAllText性能更优

内容的提问来源于stack exchange,提问作者Anonymous

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 23:10:27