27

所以我一直在阅读我不应该编写自己的 CSV 读取器/写入器,所以我一直在尝试使用通过 nuget 安装的 CsvHelper 库。CSV 文件是灰度图像,行数为图像高度,列数为宽度。我想将值逐行读取到单个List<string>orList<byte>中。

我到目前为止的代码是:

using CsvHelper;

public static List<string> ReadInCSV(string absolutePath)
{
    IEnumerable<string> allValues;

    using (TextReader fileReader = File.OpenText(absolutePath))
    {
        var csv = new CsvReader(fileReader);
        csv.Configuration.HasHeaderRecord = false;
        allValues = csv.GetRecords<string>
    }

    return allValues.ToList<string>();
}

但是allValues.ToList<string>()抛出一个:

用户代码未处理 CsvConfigurationException

CsvHelper.dll 中出现“CsvHelper.Configuration.CsvConfigurationException”类型的异常,但未在用户代码中处理

附加信息:不能自动映射继承 IEnumerable 的类型。您是否不小心调用了作用于单个记录的 GetRecord 或 WriteRecord,而不是调用作用于记录列表的 GetRecords 或 WriteRecords?

GetRecords可能期待我自己的自定义类,但我只是想要一些原始类型或字符串的值。另外,我怀疑整行都被转换为单个字符串,而不是每个值都是单独的字符串。

4

6 回答 6

29

根据@Marc L 的帖子,你可以试试这个:

public static List<string> ReadInCSV(string absolutePath) {
    List<string> result = new List<string>();
    string value;
    using (TextReader fileReader = File.OpenText(absolutePath)) {
        var csv = new CsvReader(fileReader);
        csv.Configuration.HasHeaderRecord = false;
        while (csv.Read()) {
           for(int i=0; csv.TryGetField<string>(i, out value); i++) {
                result.Add(value);
            }
        }
    }
    return result;
}
于 2015-10-23T04:45:36.980 回答
17

如果您只需要数组中每一行的字符串值,则可以直接使用解析器。

var parser = new CsvParser( textReader );
while( true )
{
    string[] row = parser.Read();
    if( row == null )
    {
        break;
    }
}

http://joshclose.github.io/CsvHelper/#reading-parsing

更新

版本 3 支持读取和写入IEnumerable属性。

于 2015-10-23T16:00:12.863 回答
3

请试试这个。这对我有用。

TextReader reader = File.OpenText(filePath);
            CsvReader csvFile = new CsvReader(reader);
            csvFile.Configuration.HasHeaderRecord = true;
            csvFile.Read();
            var records = csvFile.GetRecords<Server>().ToList();

服务器是一个实体类。这就是我创建的方式。

 public class Server
    {
        private string details_Table0_ProductName;
        public string Details_Table0_ProductName
        {
            get
            {
                return details_Table0_ProductName;
            }
            set
            {
                this.details_Table0_ProductName = value;
            }
        }

        private string details_Table0_Version;
        public string Details_Table0_Version
        {
            get
            {
                return details_Table0_Version;
            }
            set
            {
                this.details_Table0_Version = value;
            }
        }       
    }
于 2017-06-02T14:43:32.250 回答
3

这里的重点是读取 CSV 的所有行并将其反序列化为对象集合。我不确定你为什么要将它作为字符串的集合来阅读。ReadAll()如前所述,在这种情况下,通用可能最适合您。当您将它用于此目的时,该库会发光:

using System.Linq;

...
using (var reader = new StreamReader(path))
using (var csv = new CsvReader(reader))
{
    var yourList = csv.GetRecords<YourClass>().ToList();
}

如果您不使用ToList()- 它会一次返回一条记录(以获得更好的性能),请阅读https://joshclose.github.io/CsvHelper/examples/reading/enumerate-class-records

于 2018-12-31T20:17:45.577 回答
0

你很亲密。并不是它试图将转换为字符串。CsvHelper 尝试使用标题行中给出的名称将行中的每个字段映射到您给它的类型的属性。此外,它不了解如何对IEnumerable类型(string实现)执行此操作,因此它只是在自动映射到测试类型时抛出。


这对你正在做的事情来说很复杂。如果您的文件格式足够简单(您的文件格式似乎是众所周知的字段格式,既没有转义也没有引用分隔符),我认为您没有理由需要承担导入库的开销。您应该能够根据需要使用System.IO.File.ReadLines()和枚举值String.Split()

//pseudo-code...you don't need CsvHelper for this
IEnumerable<string> GetFields(string filepath)
{
  foreach(string row in File.ReadLines(filepath))
  {
    foreach(string field in row.Split(',')) yield return field;
  }
}
于 2015-10-23T04:34:23.007 回答
-2
static void WriteCsvFile(string filename, IEnumerable<Person> people)
    {

        StreamWriter textWriter = File.CreateText(filename);

        var csvWriter = new CsvWriter(textWriter, System.Globalization.CultureInfo.CurrentCulture);

        csvWriter.WriteRecords(people);

        textWriter.Close();

    }
于 2020-02-19T19:26:03.250 回答