首页 > 解决方案 > 使用 LINQ 将 CSV 读取到对象时出现字符串格式错误

问题描述

我正在将 CVS 文件中的数据读入 C# 列表对象。我只能读取字符串值。当我尝试读取一个数值(在这种情况下为双精度)时,我得到输入字符串格式不正确的异常。任何人都可以告诉我如何克服这个问题?这是代码:

班级 :

 public class Loan
    {
        string applicationDT;
        string employeeID;
        string employeeName;
        double amount;
        string lonType;

        public void printLoan()
        {
            Console.WriteLine($" employeeName {employeeName} employee Id {employeeID}" +
                $"applicationDate {applicationDT} \namount {amount} loanType {lonType}");
        }

        public static Loan fromCVS(string csvLine)
        {
            string []values = csvLine.Split(',');
            Loan loanRecord = new Loan();
            loanRecord.employeeName = (values[3]);
            loanRecord.employeeID = (values[4]);
            loanRecord.applicationDT = (values[5]);
            loanRecord.amount = Convert.ToDouble(values[6]);
            loanRecord.lonType = (values[7]);
            return loanRecord;
        }
    }

主要的:

static void Main()
{
    List<Loan> loans = File.ReadAllLines(@"C:\Users\0300Test.csv")
                                   .Skip(1)
                                   .Select(v => Loan.fromCVS(v))
                                   .ToList();
    foreach(Loan aLoan in loans)
    {
        aLoan.printLoan();
    }
}

CSV 文件:

"APPROVAL_OFFICER_NAME","APPROVAL_OFFICER_ID","RELATIONSHIP_MANAGER_NAME","EMPLOYEE_NAME","EMPLOYEE_ID","APPLICATION_DATE_TIME","AMOUNT","TYPE_OF_LOAN"
"SAMPLNAME","988803","SAMPLNAME","SAMPLNAME","776667","1/22/2019 11:05:43 AM","321146.00","Top Up With Settlement"
"SAMPLNAME","988803","SAMPLNAME","SAMPLNAME","776667","1/22/2019 9:34:13 AM","90230.00","Top Up With Settlement"
"SAMPLNAME","988803","SAMPLNAME","SAMPLNAME","776667","1/22/2019 12:00:22 AM","5230.00","Top Up without Settlement"

标签: c#linqcsvdouble

解决方案


显然你的问题是当你想为amount

string []values = csvLine.Split(',');
double amount = Convert.ToDouble(values[6]);

当然,您调试了代码。你认为有什么价值values[6]

从您的 csv 行示例中,它看起来像:"\"90230.00\""

所以它是一个以字符串引号开头和结尾的字符串。无法将此值转换为双精度值。

解决方法很简单:去掉这个值开头和结尾的字符串引号。

  amount = Double.Parse(value[6].SubString(1, value[6].Length-2));

顺便说一句,您希望employeeName(和所有其他人)成为字符串 SAMPLENAME 还是应该用引号括起来:“SAMPLENAME”(所以在内部是“\”SAMPLENAME\“”)?

如果要从所有值中删除这些开始和结束字符串引号,请考虑为字符串创建扩展函数。请参阅揭秘的扩展方法

public static IEnumerable<string> SplitAndRemoveQuotes(this string string)
{
    // TODO: handle null string
    var splitValues = string.Split(',');
    foreach(string splitValue in splitValues)
    {
         // if you are certain every split value starts and ends with string quote
         // TODO: throw exception if not start/end with string quote?
         yield return splitValue.SubString(1, splitValue.Length-2);
    }
}

因此,如果您的字符串格式为 "\"\"\"",(可读格式:"""),则返回值将是一个只有一个引号 (") 的字符串

用法:

public static Loan fromCVS(string csvLine)
{
    // TODO: exception if csvLine null or empty

    var splitWithoutQuotes = csvLine.SplitAndRemoveQuotes()
        .Skip(2)        // we don't need the first two values
        .Take(5)        // we only need the next five values
        .ToList();
    // TODO: exception if result not 5 items

    return new Loan
    {
        employeNames = splitWithoutQuotes[0],
        ...
        amount = Double.Parse(values[4]);
        ...
    };
}

推荐阅读