尝试从CsvHelper遍历记录会抛出ConfigurationException错误

时间:2019-06-17 09:46:26

标签: c# unity3d automapper ienumerable csvhelper

我正在尝试遍历.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()方法,但无济于事。


Edit1:

尝试创建自定义类后,我遇到了另一个错误,这次是在编译器甚至无法运行代码之前发生的。

本质上,在这段代码中:

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

foreach突出显示,并显示错误消息“无法将类型'instructions.ScriptsList'转换为'string'”。我的文件名为“ instructions.cs”。

一些额外的信息也可能是问题所在

1)我正在IEnumerator中编写这段代码,但是我认为那不应该是一个问题,因为我确实有其他“ foreach”行。除非CsvHelper使用某些在IEnumerator中无法使用的代码?

2)我的.csv文件是在excel中创建的,并且确实具有标头。实际上,它只是“是”和“否”的多个列。在Excel中创建并将其另存为.csv(逗号分隔)是否会影响CsvHelper对其的读取方式?

3)在该函数上方编写类是否重要? (我知道这是一种基本的方法,但是我对C#还是很陌生,我已经注意到,在许多文档中,该类通常写在该函数的下面)

非常感谢您的帮助!

2 个答案:

答案 0 :(得分:1)

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

您想给GetRecords<>一个类或结构,它将使用您的.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文件缺少标题行(即,第一行指定了每一列所代表的内容),则可以将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; }
}

但是,如果您只是逐行读取文件中的每一行,我建议您仅使用StreamReaderFile.OpenRead或简单地使用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 :(得分:1)

对于您的更新问题:

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

  2. 否。如果文件classstructenum占用相同的文件/示例,则通常在文件的底部和类的下方写入bookListexport default { name: "BookList", // template name apollo: { bookList: { query: getBooksQuery // query } } } apollo: { bookList: getBooksQuery } 。它是C#语法的一部分,并且C#编译器不需要要求类型定义的特定位置。这与您使用自上而下的方法编写的代码不同,而类型定义遵循的是树状结构。

    您使用C#编写的代码流只是C#完整语法的一部分。我认为C#的强大功能来自其语法的其余部分,包括名称空间,属性,枚举器方法,可访问性修饰符等。