使用CSVHelper解析通话日志CSV时无法获取Date字段的技术问询
解析CSV通话日志时Date字段无法获取的解决方案
问题
有一个.txt格式的CSV通话日志,定义的字段为Name、Address、Direction、Status、Duration、Date,使用CSVHelper解析时无法正确获取Date字段,需要开发Windows窗体程序存储包含完整日期时间的通话日志。
日志示例
Name,Address,Direction,Status,Duration,Date Berat Bey Dörtsan,"05315554622",Outgoing,Unanswered,00:00,00:00,8/4/2022 (9:25:48 AM) Berat Bey Dörtsan,"05315554622",Outgoing,Answered,00:47,00:47,8/4/2022 (9:27:55 AM)
预期解析格式
- Name = Berat Bey Dörtsan
- Address = 05315554466
- Direction = Outgoing
- Status = Unanswered
- Duration = 00:54 - 01:56
- Date = 8/4/2022 (9:25:48 AM)
用户原有代码
using CsvHelper; using CsvHelper.Configuration.Attributes; using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Globalization; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace TextVeriCekme { public partial class Form1 : Form { String csvPath = ""; public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { OpenFileDialog ofd = new OpenFileDialog { Title = "CSV Dosyası Aç", Filter = "csv files (*.csv)|*.csv", CheckFileExists = true, CheckPathExists = true }; if (ofd.ShowDialog() == DialogResult.OK) { MessageBox.Show(ofd.FileName); csvPath = ofd.FileName; } } public class Foo { public string Name { get; set; } public string Address { get; set; } public string Direction { get; set; } public string Status { get; set; } public string Duration { get; set; } [Name("Date")] [Format("dd-MM-yyyy")] public DateTime Date { get; set; } } int sayac = 0; private void button2_Click(object sender, EventArgs e) { IEnumerable<Foo> records = null; List<Foo> list = null; using (var reader = new StreamReader(csvPath)) using (var csv = new CsvReader(reader, CultureInfo.InvariantCulture)) { records = csv.GetRecords<Foo>(); list = records.ToList(); MessageBox.Show("Toplam Kayıt : " + records.Count().ToString()); foreach (Foo record in list) { if (sayac == 1) { MessageBox.Show(record.Name); MessageBox.Show(record.Address); MessageBox.Show(record.Direction); MessageBox.Show(record.Status); MessageBox.Show(record.Duration); MessageBox.Show(record.Date.ToString()); } sayac++; } } } } }
问题原因及解决步骤
1. 字段不匹配:表头与数据列数量不一致
日志表头仅定义6个字段,但实际数据行有7列——Duration对应了两个值(如00:00,00:00),导致Date字段的位置被偏移,CSVHelper无法正确映射。
2. Date字段格式配置错误
日志中的日期格式为M/d/yyyy (h:mm:ss tt)(示例:8/4/2022 (9:25:48 AM)),但代码中使用[Format("dd-MM-yyyy")],格式不匹配导致解析失败。
修改后的代码实现
using CsvHelper; using CsvHelper.Configuration; using CsvHelper.Configuration.Attributes; using System; using System.Collections.Generic; using System.Globalization; using System.IO; using System.Linq; using System.Windows.Forms; namespace TextVeriCekme { public partial class Form1 : Form { string csvPath = ""; public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { OpenFileDialog ofd = new OpenFileDialog { Title = "CSV Dosyası Aç", Filter = "csv files (*.csv)|*.csv", CheckFileExists = true, CheckPathExists = true }; if (ofd.ShowDialog() == DialogResult.OK) { MessageBox.Show(ofd.FileName); csvPath = ofd.FileName; } } // 修正实体类,匹配实际数据列 public class CallLog { public string Name { get; set; } public string Address { get; set; } public string Direction { get; set; } public string Status { get; set; } // 接收第一个Duration值 [Name("Duration")] public string DurationStart { get; set; } // 接收第二个Duration值,通过索引指定位置 [Index(5)] public string DurationEnd { get; set; } // 匹配日志中的日期格式 [Index(6)] [Format("M/d/yyyy (h:mm:ss tt)")] public DateTime Date { get; set; } // 合并Duration为预期格式 public string FormattedDuration => $"{DurationStart} - {DurationEnd}"; } int sayac = 0; private void button2_Click(object sender, EventArgs e) { if (string.IsNullOrEmpty(csvPath)) { MessageBox.Show("请先选择CSV文件"); return; } // 配置CSVHelper文化信息,适配日期解析 var config = new CsvConfiguration(CultureInfo.InvariantCulture) { // 确保表头映射正确 HasHeaderRecord = true, }; using (var reader = new StreamReader(csvPath)) using (var csv = new CsvReader(reader, config)) { var records = csv.GetRecords<CallLog>().ToList(); MessageBox.Show("Toplam Kayıt : " + records.Count.ToString()); foreach (var record in records) { if (sayac == 1) { MessageBox.Show(record.Name); MessageBox.Show(record.Address); MessageBox.Show(record.Direction); MessageBox.Show(record.Status); MessageBox.Show(record.FormattedDuration); // 使用合并后的Duration MessageBox.Show(record.Date.ToString("M/d/yyyy (h:mm:ss tt)")); } sayac++; } } } } }
关键修改说明
- 实体类重命名为
CallLog更具语义,新增DurationStart和DurationEnd分别接收数据中的两个时长值,通过[Index]特性指定第二个时长的列位置。 - 新增
FormattedDuration属性,将两个时长值合并为预期的00:00 - 00:00格式。 - Date字段修改为
[Format("M/d/yyyy (h:mm:ss tt)")],匹配日志中的日期格式,同时通过[Index(6)]明确指定列位置,避免表头映射歧义。 - 添加CSV配置实例,确保文化信息正确,同时增加文件路径为空的判断。
内容的提问来源于stack exchange,提问作者philante
相关产品推荐
相关产品推荐

