【问题标题】:Setting variable types from CSV从 CSV 设置变量类型
【发布时间】:2012-08-31 14:46:18
【问题描述】:
var csv =
    from line in File.ReadAllLines("C:/file.csv")
    let customerRecord = line.Split(',')
    select new Customer()
        {
            contactID = customerRecord[0],
            surveyDate = customerRecord[1],
            project = customerRecord[2],
            projectCode = customerRecord[3]
        };

public class Customer
    {
        public string contactID { get; set; }
        public string surveyDate { get; set; }
        public string project { get; set; }
        public string projectCode { get; set; }
    }

我希望能够将surveyDate 读取为DateTime,以便将其与我要加入csv 文件的其他DateTime 字段进行比较。

我尝试在课程中将surveyDate 设置为 Date.Time,并尝试在 select 语句中对其进行转换,但都失败并出现以下错误:

FormatException:字符串未被识别为有效的 DateTime。从索引 0 开始有一个未知单词。

我必须使用 csv 文件,所以我无法将数据添加到 sql server。

contactID,responseDate,project,projectID
1,6/4/2009,0-3 个月,1
2,6/11/2009,0-3 个月,1

【问题讨论】:

  • -1 “但都失败了” 这是什么意思,代码在哪里?
  • 您在 customerRecord[1] 中的内容
  • contactID,responseDate,project,projectID 1,6/4/2009,0-3 月,1 2,6/11/2009,0-3 月,1

标签: c# linq


【解决方案1】:

在读取和更改类型时需要对其进行解析。我不确定你一开始是如何尝试的。另外,如果您知道格式,请使用DateTime.ParseExact

var csv =
    from line in File.ReadAllLines("C:/file.csv")
    let customerRecord = line.Split(',')
    select new Customer()
        {
            contactID = customerRecord[0],
            surveyDate = DateTime.Parse(customerRecord[1]),
            project = customerRecord[2],
            projectCode = customerRecord[3]
        };

public class Customer
{
    public string contactID { get; set; }
    public DateTime surveyDate { get; set; }
    public string project { get; set; }
    public string projectCode { get; set; }
}

从您刚刚发布的错误来看,我认为它可能是双引号。尝试修剪引号:

DateTime.Parse(customerRecord[1].Trim('"'))

【讨论】:

  • 这和我第一次尝试的完全一样。例如,在 csv 文件中,日期存储为 2009 年 6 月 4 日。如果没有 DateTime.Parse 代码,我会收到一个错误:无法执行文本选择:无法将类型“字符串”隐式转换为“System.DateTime”
  • 2009 年 6 月 4 日是什么时候?是四月还是六月? (是从文本或 Excel 或 Calc 之类的东西中查看它吗?)
  • 对于这组数据,它是美国日期,但我在另一个文件中也有英国日期。此示例是 2009 年 6 月 4 日。
【解决方案2】:

对...因为您永远无法知道来自 CSV 的输入是什么,所以您不能总是尝试将字符串隐式转换为 DateTime,并且因为您想在选择方式中转换字符串这样做是一种扩展方法。

  public static class StringExtensions
  {
    public static DateTime TryParseDate(this string strToParse)
    {
      DateTime dt = new DateTime();
      DateTime.TryParse(strToParse, out dt);
      return dt;
    }
  }

然后当你想在选择中进行转换时,这样做:

  var csv = from line in File.ReadAllLines("C:/file.csv")
            let customerRecord = line.Split(',')
            select new Customer()
                {
                  contactID = customerRecord[0],
                  surveyDate = customerRecord[1].TryParseDate(),
                  project = customerRecord[2],
                  projectCode = customerRecord[3]
                };

你有你自己的方法。希望这对您有所帮助。

您要解析的字符串将被传递给方法,然后您可以处理它并返回有效的日期时间,处理不正确的输入。

http://msdn.microsoft.com/en-us/library/bb383977.aspx

查看此链接了解说明

【讨论】:

  • 感谢您的出色演练。这行得通,我明白为什么我需要指定如何处理日期。
  • 对不起卢克。我的用户错误。我在这里学习绳索。它有效。
  • 不是问题 - 只是检查您是否遇到了需要帮助的新问题:) 很高兴它工作正常。
【解决方案3】:

在更改 Customer 以使 SurveyDateDateTime 之后:

select new Customer()
    {
        contactID = customerRecord[0],
        surveyDate = DateTime.Parse(customerRecord[1]),
        project = customerRecord[2],
        projectCode = customerRecord[3]
    };

您可能需要使用采用格式字符串的ParseParseExact 形式,以确保结果正确。该格式字符串取决于文件中使用的格式。

或者,您可以在 Customer 上创建一个 Parse 静态方法:

public class Customer
{
    public string contactID { get; set; }
    public DateTime surveyDate { get; set; }
    public string project { get; set; }
    public string projectCode { get; set; }
    public static Customer Parse(string line)
    {
       var parts = line.Split(',');
       return new Customer{
         contactID = parts[0],
         surveyDate = DateTime.Parse(customerRecord[1]),
         project = customerRecord[2],
         projectCode = customerRecord[3]
      };
};

然后:

var csv =
  from line in File.ReadLines("C:/file.csv")
  select Customer.Parse(line);

如果在您的代码中不止一次地从这样的格式化字符串中获取Customer,这将具有优势。如果这是您唯一这样做的地方,它不必要地用 cruft 填充 Customer。请注意,我更喜欢 ReadLines 而不是 ReadAllLines 一次获得一条线路,而不是在开始生产客户之前阅读整个内容。

顺便说一下,.NET 约定倾向于在属性名称上使用大写字母。 SurveyDate 而不是 surveyDate 等。

【讨论】:

  • Jon - 我很欣赏关于正确命名约定的注释。根据您对客户的说明,我认为这可能是我唯一称呼它的地方。感谢您的小费。我确定我会回来的。
【解决方案4】:

我尝试在课堂上将surveyDate 设置为 Date.Time,并尝试在 select 语句中对其进行转换,但都失败了。

你需要两者都做。您需要更改属性类型(最好同时修复命名以遵循约定)更改您设置它的位置,可能使用DateTime.ParseExact,指定格式和可能的不变文化.

(我假设您知道文件中日期的格式 - 我会强烈建议您使用 DateTime.ParseExact 而不是让框架尝试各种格式,直到找到一种工作。)

编辑:现在我们已经看到了文件,看起来你想要或者

DateTime.ParseExact(text, "d/M/yyyy", CultureInfo.InvariantCulture)

或:

DateTime.ParseExact(text, "M/d/yyyy", CultureInfo.InvariantCulture)

...但我们不知道是哪一个,因为我们不知道“2009 年 6 月 4 日”是指 4 月 6 日还是 6 月 4 日。

【讨论】:

  • FormatException:字符串未被识别为有效的日期时间。从索引 0 开始有一个未知单词。
  • @JimMelichar:这表明您使用了错误的格式。由于您没有告诉我们这些值是什么样的或您尝试过什么,因此很难进一步提供帮助......
  • 吉姆,乔恩在这里是正确的,这不是我所期望的错误。这个日期是什么格式的? (向你保证我的回答也不会奏效,但知道这种格式会让我们中的任何一个乔恩弄清楚)。
  • @JimMelichar:在文本编辑器中打开它。如果它被引用,那么,这就是你的问题......或一个问题。
  • 如果是6/9/2009,是指 9 月 6 日还是 6 月 9 日?如果它来自 Excel,它很可能类似于 40396,因为它有时会将日期和时间存储为从 1899-01-30 开始的天数(或者接近那个时间,我记不清了)。跨度>
【解决方案5】:

您应该将customerRecord[1] 字符串转换为DateTime

var csv =
    from line in File.ReadAllLines("C:/file.csv")
    let customerRecord = line.Split(',')
    select new Customer()
        {
            contactID = customerRecord[0],
            surveyDate = DateTime.Parse(customerRecord[1]),
            project = customerRecord[2],
            projectCode = customerRecord[3]
        };

public class Customer
    {
        public string contactID { get; set; }
        public DateTime surveyDate { get; set; }
        public string project { get; set; }
        public string projectCode { get; set; }
    }

【讨论】:

    猜你喜欢
    • 2019-01-01
    • 2018-11-22
    • 1970-01-01
    • 2021-12-25
    • 1970-01-01
    • 2010-09-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多