【问题标题】:Dotnet CSV Helper Unable to Parse fileDotnet CSV Helper 无法解析文件
【发布时间】:2019-10-11 19:04:17
【问题描述】:

我正在尝试将 csv 文件解析为给定类的项目列表。我对 dotnet 世界很陌生。我正在使用 .NET (2.2.402) 这是我班级的代码

public class ItemResource
{ 
    public string Msisdn { get; set; }
    public float Amount { get; set; }
    public string PersonName { get; set; }
    public string Message { get; set; }
    public string Description { get; set; }

    /// <summary>
    /// Tells wether or not the customer will receive a notification
    /// </summary>
    /// 
    public int Notify { get; set; }
}

这是我尝试解析文件的代码部分

StreamReader reader = new StreamReader("path-to-file.csv");

var csvReader = new CsvReader(reader);

//csvReader.Configuration.Delimiter = ";";
//csvReader.Configuration.HeaderValidated = null;
var records = csvReader.GetRecords<ItemResource>();

_logger.LogInformation(records.Count().ToString());

foreach(var record in records)
{
    _logger.LogInformation(record.ToString());
}

这是文件的内容

Msisdn, Amount, PersonName, Message, Description, Notify
69947943,150,Name 1,TEST,Test,1
69947943,150,Name 2,TEST,Test,1
69947943,150,Name 3,TEST,Test,1
69947943,150,Name 4,TEST,Test,1
69947943,150,Name 4,TEST,Test,1
69947943,150,Name 5,TEST,Test,1

正如您所看到的,为了测试,我对路径进行了编码。这是我遇到的错误

CsvHelper.HeaderValidationException:名称为“Msisdn”的标头不是 成立。如果您期望某些标题丢失并且想要 忽略此验证,将配置 HeaderValidated 设置为 null。 您还可以更改功能以执行其他操作,例如 记录问题。在 CsvHelper.Configuration.ConfigurationFunctions.HeaderValidated(布尔 isValid, String[] headerNames, Int32 headerNameIndex, ReadingContext 上下文)在 CsvHelper.CsvReader.ValidateHeader(ClassMap map) 在 CsvHelper.CsvReader.GetRecordsT+MoveNext() 在 System.Linq.Enumerable.Count[TSource](IEnumerable`1 源)在 OMBulkPayment.Controllers.PaymentsController.Payment(SavePaymentResource 资源)在 C:\Users\BMHB8456\source\repos\OMBulkPayment\OMBulkPayment\Controllers\PaymentsController.cs:line 59 at lambda_method(Closure, Object, Object[]) at Microsoft.Extensions.Internal.ObjectMethodExecutor.Execute(对象 目标,对象 [] 参数)在 Microsoft.AspNetCore.Mvc.Internal.ActionMethodExecutor.SyncActionResultExecutor.Execute(IActionResultTypeMapper 映射器,ObjectMethodExecutor 执行器,对象控制器,Object[] 论据)

【问题讨论】:

  • 它在第一行的第一个字段上失败。这有时表明存在更大的问题,例如该文件实际上是空白的,包含无效字符,甚至顶部只有一个空行。检查文件。
  • 我在 Windows 10 操作系统上工作,切换到 Macos High Sierra 后,我得到了确切的错误

标签: c# .net csvhelper


【解决方案1】:

显式设置分隔符。换行

//csvReader.Configuration.Delimiter = ";";

csvReader.Configuration.Delimiter = ",";

默认分隔符取决于系统称为列表分隔符的区域设置。

同时删除 csv 文件标题名称之间的空格。如下所示:

Msisdn,Amount,PersonName,Message,Description,Notify

【讨论】:

    【解决方案2】:

    使用CSVHelper 很好,它是一个开源项目,是我发现使用的最简单的库。

    我对您的测试数据进行了以下尝试,并且能够成功地使其工作:

    void Main()
    {
        using (var reader = new StreamReader("D:\\PROJECTS\\2019\\DVP_Salary_Payment_Local\\Payment\\test_2.csv"))
        using (var csv = new CsvReader(reader))
        {
            csv.Configuration.Delimiter = ",";
            var records = csv.GetRecords<ItemResource>();
        }
    }
    
    public class ItemResource
    {
        public string Msisdn { get; set; }
    
        public float Amount { get; set; }
    
        public string PersonName { get; set; }
    
        public string Message { get; set; }
    
        public string Description { get; set; }
    
        public int Notify { get; set; }
    }
    

    您可以在他们的网站here 上查看几乎相同的示例。

    【讨论】:

      【解决方案3】:

      不太确定 CsvHelper,但您并不需要任何额外的组件来原生读取 CSV 文件...您可以使用 OleDb 将其作为平面数据文件读取:

      public DataTable ReadCsv(string filename, bool hasHeaders = true, string delimiter = ",")
      {
          var dt = new System.Data.DataTable();
      
          var fi = new System.IO.FileInfo(filename);
      
          var connStr = string.Format("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=\"{0}\";Extended Properties='text;HDR={1};FMT=Delimited({2})';",
                                      fi.DirectoryName,
                                      ((hasHeaders) ? "Yes" : "No"),
                                      delimiter);
      
          var commStr = string.Format("SELECT * FROM [{0}]", fi.Name);
      
          using (var conn = new System.Data.OleDb.OleDbConnection(connStr))
          using (var cmd = new System.Data.OleDb.OleDbCommand(commStr, conn))
          using (var adapter = new System.Data.OleDb.OleDbAdapter(cmd))
          {
              adapter.Fill(dt);
          }
      
          return dt;
      }
      

      这还有一个好处是能够通过更改 SELECT 查询来查询要返回的特定行,您也可以将其作为参数传递。如果您绝对想要输入数据而不是字符串,只需在数据表上手动创建列,然后在适配器上调用 Fill()。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-07-19
        • 1970-01-01
        • 2023-02-01
        • 2017-07-01
        • 2018-07-05
        相关资源
        最近更新 更多