【问题标题】:CSV to object model mappingCSV 到对象模型的映射
【发布时间】:2011-03-30 16:31:13
【问题描述】:

我有一个要读入列表的 CSV 文件。这是一个示例文件:

Plant,Material,"Density, Lb/ft3",Storage Location
FRED,10000477,64.3008,3300
FRED,10000479,62.612,3275
FRED,10000517,90,3550
FRED,10000517,72,3550
FRED,10000532,90,3550
FRED,10000532,72,3550
FRED,10000550,97,3050

我知道我可以手动读取 CSV 文件并使用普通 StreamReader 构建列表,但我想知道是否有更好的方法,也许使用 LINQ?

【问题讨论】:

  • 要列出什么?你有这方面的课程吗?匿名类型可以吗?
  • 我有一个类代表 csv 中的数据。

标签: c# linq csv


【解决方案1】:

您可以使用这样的简单代码,它会忽略标题并且不能使用引号,但可能足以满足您的需求。

from line in File.ReadAllLines(fileName).Skip(1)
let columns = line.Split(',')
select new
{
  Plant = columns[0],
  Material = int.Parse(columns[1]),
  Density = float.Parse(columns[2]),
  StorageLocation = int.Parse(columns[3])
}

或者您可以像其他人建议的那样使用库。

【讨论】:

  • @terphi 这需要使用引号,就像我说的那样,我的代码无法使用。
  • 对不起,我猜我是略读了。
【解决方案2】:

对于您问题中显示的具体数据...

var yourData = File.ReadAllLines("yourFile.csv")
                   .Skip(1)
                   .Select(x => x.Split(','))
                   .Select(x => new
                                {
                                    Plant = x[0],
                                    Material = x[1],
                                    Density = double.Parse(x[2]),
                                    StorageLocation = int.Parse(x[3])
                                });

如果您已经为您的数据声明了一个类型,那么您可以使用它而不是匿名类型。

请注意,此代码一点也不可靠。它无法正确处理包含逗号/换行符等、带引号的字符串值或 CSV 文件中常见的任何其他深奥内容的值。

【讨论】:

  • 我正在尝试找出一种方法,其中列:植物、材料 .... 可以在运行时定义,有什么解决方案吗?
【解决方案3】:

有一个代码项目:

http://www.codeproject.com/KB/linq/LINQtoCSV.aspx

不过,你可能想看看这里:

Linq and streamreader getting lines

【讨论】:

    【解决方案4】:

    我编写了一个简单的库来允许开发人员在 CSV 文件上使用 LINQ。这是我的博客文章:http://procbits.com/2010/10/11/using-linq-with-csv-files/

    在您的情况下,您必须将标题字符串更改为如下所示:

    Plant,Material,DensityLbft3,StorageLocation
    

    然后你可以像这样解析文件:

    var linqCSV = new CsvToXml("csvfile", true);
    linqCsv.TextQualifier = null;
    
    linqCsv.ColumnTypes.Add("Plant", typeof(string));
    linqCsv.ColumnTypes.Add("Material", typeof(int));
    linqCsv.ColumnTypes.Add("DensityLbft3", typeof(double));
    linqCsv.ColumnTypes.Add("StorageLocation", typeof(int));
    
    linqCsv.Convert();
    

    然后您可以像这样使用 LINQ:

    var items = from item in linqCsv.DynamicRecords
                where item.Plant == "Fred" && item.DensityLbft3 >= 62.6
                orderby item.StorageLocation
                select item;
    

    希望对您有所帮助或工作。

    【讨论】:

      【解决方案5】:

      带有Cinchoo ETL库,可以将CSV文件解析成对象

      定义类型匹配的CSV文件结构如下

      public class PlantType
      {
          public string Plant { get; set; }
          public int Material { get; set; }
          public double Density { get; set; }
          public int StorageLocation { get; set; }
      }
      

      加载 CSV 文件

      static void LoadCSV()
      {
          using (var p = new ChoCSVReader<PlantType>("*** YOUR CSV FILE PATH ***")
              .WithFirstLineHeader(true)
              )
          {
              foreach (var rec in p)
              {
                  Console.WriteLine(rec.Dump());
              }
          }
      }
      

      【讨论】:

        【解决方案6】:

        它不使用 LINQ,但 CsvHelper 是一种将 CSV 解析为 .NET 对象的简单方法:

        using (TextReader txt = new StreamReader(filename))
        {
            using (var csv = new CsvReader(txt))
            {
                var records = csv.GetRecords<PlantMaterial>();
                return records.ToList();
            }
        }
        

        【讨论】:

          猜你喜欢
          • 2010-10-05
          • 2015-08-27
          • 1970-01-01
          • 2015-07-01
          • 2014-12-27
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多