尝试遍历 CsvHelper 中的记录会引发 ConfigurationException 错误

Trying to iterate over records from CsvHelper throws ConfigurationException error

我正在尝试遍历 .csv 文件以在控制台上输出。我正在使用 CsvHelper 并按照 T 的指南进行操作,但是每当我尝试遍历从 GetRecords() 方法获得的 IEnumerable 时,就会出现 ConfigurationException。

这是我正在使用的代码

using (var reader_ans = new StreamReader("scriptlists/prac_iden_ans.csv"))
using (var csv_ans = new CsvReader(reader_ans))
{
    var ans = csv_ans.GetRecords<string>();

    foreach (string item in ans)
    {
        Debug.Log(item);
    }
}

这很奇怪,因为这正是文档和多个网站中的内容。

出现的错误是这样的:

ConfigurationException: Types that inherit IEnumerable cannot be auto mapped. Did you accidentally call GetRecord or WriteRecord which acts on a single record instead of calling GetRecords or WriteRecords which acts on a list of records?

我想知道我是否遗漏了一些愚蠢的东西,因为我是 C# 的新手。我也在 Unity3D 中对此进行编码,所以这可能是问题的一部分吗?

我也尝试在第一行使用 .ToList() 方法,但无济于事。


编辑 1:

在尝试创建自定义 class 之后,我 运行 进入了另一个错误,这次是在我什至 运行 代码之前来自编译器。

本质上,在这段代码中:

foreach (string item in ans)
            {
                Debug.Log(item);
            }

foreach 被高亮显示并显示一条错误 "Cannot convert type 'instructions.ScriptsList' to 'string'"。我的文件名为 "instructions.cs".

还有一些可能是问题所在的额外信息:

1) 我正在 IEnumerator 中编写这段代码,但我不认为这应该是一个问题,因为我在其中还有其他 "foreach" 行。除非 CsvHelper 使用某些在 IEnumerator 中不起作用的代码?

2) 我的 .csv 文件是在 excel 中创建的,它们确实有 headers。它实际上只是 "Yes" 和 "No" 的多个列。在 Excel 中创建它并将其保存为 .csv(逗号分隔)是否会影响 CsvHelper 读取它的方式?

3) class 写在这个函数上面有关系吗? (我知道这是基本的,但我是 C# 的新手,我注意到在很多文档中 class 通常写在函数下面)

非常感谢您的帮助!

您收到的错误消息是指它无法使用给定的配置进行填充。

您想给 GetRecords<> 一个 class 或结构,它将用 .csv 中每一行的值填充。您的脚本可能由于尝试将行填充到 string 类型而失败。

示例解决方案,鉴于您的 .csv 看起来与此类似:

您的 prac_iden_ans.csv 文件:

Path
C:/example/path/one
C:/example/path/two

您的 .cs C# 脚本文件:

void YourFunction() {

    using (var reader_ans = new StreamReader("scriptlists/prac_iden_ans.csv"))
    using (var csv_ans = new CsvReader(reader_ans))
    {
        var ans = csv_ans.GetRecords<ScriptsList>();

        foreach (ScriptsList item in ans)
        {
            Debug.Log(item.Path);
        }
    }

}

class ScriptsList {
    public string Path { get; set; }
}

但是,如果您的 .csv 文件缺少 header 行(即第一行指定每列代表的内容),您可以将 CsvReader 配置为不期望。但是,您必须以不同的方式告诉 CsvReader 哪些列映射到哪些属性。一种方法是 IndexAttribute。示例:

您的 prac_iden_ans.csv 文件:

C:/example/path/one
C:/example/path/two

您的 .cs C# 脚本文件:

void YourFunction() {

    using (var reader_ans = new StreamReader("scriptlists/prac_iden_ans.csv"))
    using (var csv_ans = new CsvReader(reader_ans))
    {
        csv_ans.Configuration.HasHeaderRecord = false;
        var ans = csv_ans.GetRecords<ScriptsList>();

        foreach (ScriptsList item in ans)
        {
            Debug.Log(item.Path);
        }
    }

}

class ScriptsList {
    [Index(0)]
    public string Path { get; set; }
}

但如果您只是逐行阅读文件中的每一行,我建议您只使用 StreamReader, File.OpenRead, or simply File.ReadAllLines。示例:

您的 prac_iden_ans.csv 文件:

C:/example/path/one
C:/example/path/two

您的 .cs C# 脚本文件:

string[] ans = File.ReadAllLines("scriptlists/prac_iden_ans.csv");

foreach (string item in ans)
{
    Debug.Log(item);
}

对于您更新的问题:

  1. 这是我的错字。忘记将 foreach 项目变量从 string 更改为 ScriptsList。我已经更新了我的答案。您的代码段应该是:
foreach (ScriptsPath item in ans)
{
    Debug.Log(item);
}
  1. 没有。没有区别。唯一需要注意的是,有时 .csv 的格式为分号 ; 而不是逗号 , 作为分隔符。但是 .csv 是最基本的格式之一

  2. 没有。如果 classstructenum 占用相同的 file/example,则通常将其写在文件底部和 class 下方。它是 C# 语法的一部分,C# 编译器 需要类型定义的特定位置。这与您在 top-to-bottom 方法中编写的代码不同,而类型定义遵循更广泛的 tree-like 结构。

    您用 C# 编写的代码流只是 C# 完整语法的一部分。在我看来,C# 的强大之处在于它的其余语法,例如名称空间、属性、枚举器方法、可访问性修饰符等。