简体   繁体   中英

Reading a CSV file using CsvHelper

I'm a newbie. I want to get data from the CSV file-the Id and Name fields, but when I run the reading method, I get only 100 lines of an incomprehensible type: "CsvHelper.CsvReaderd__87`1[Program+Product]". I do not know how to get data from CSV, I also cannot understand where the error is.

Although the documentation says that having the same names of properties and CSV headers, you do not need to write additional configurations. However, I get the result specified above. The CSV names match the classes. Link to the documentation: https://joshclose.github.io/CsvHelper/getting-started/

reading method:

  {
        using (var reader = new StreamReader("C:\\Users\\Saint\\Desktop\\TaskRetail\\file.csv", Encoding.UTF8))
        using (var csv = new CsvReader(reader, CultureInfo.InvariantCulture))
        {
            var records = csv.GetRecords<Product>();
            Console.WriteLine($"{records}");
        }
    }

CSV is created without problems, there are two columns with Id and Name with filled rows, there are 100 rows in total:

在此处输入图片说明

method for creating a csv with the Id and Name fields:

   using (var writer = new StreamWriter("C:\\Users\\Saint\\Desktop\\TaskRetail\\file.csv", false, Encoding.UTF8))
    using (var csv = new CsvWriter(writer, CultureInfo.InvariantCulture))
    {
        csv.WriteRecords(products);
    }

the entire code:

using CsvHelper;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Net;
using System.Text;
using System.Xml;

public class Program
{

    public class Product
    {
        public int Id { get; set; }
        public string Name { get; set; }

        public Product(int id, string name)
        {
            Id = id;
            Name = name;
        }
    }
    public const string PathToDoc = "C:/Users/Saint/Desktop/TaskRetail/yml.xml";


    public static void Main(string[] args)
    {
        string url = "https://www.googleapis.com/drive/v3/files/1sSR9kWifwjIP5qFWcyxGCxN0-MoEd_oo?alt=media&key=AIzaSyBsW_sj1GCItGBK0vl8hr9zu1I1vTI1Meo";
        string savePath = @"C:\Users\Saint\Desktop\TaskRetail\yml.xml";
        WebClient client = new WebClient();
        client.DownloadFile(url, savePath);

        Research();
    }

    public static void Research()
    {
        Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);

        var document = new XmlDocument();
        document.Load(PathToDoc);
        var xmlDoc = document.SelectNodes("/yml_catalog/shop/offers/offer");
        var count = xmlDoc.Count;
        var products = new List<Product>();
        Console.WriteLine($"Offers count: {count}");
        for (var i = 0; i < count; i++)
        {
            var element = xmlDoc.Item(i);
            var id = int.Parse(element.Attributes.GetNamedItem("id").Value);
            var name = element.SelectSingleNode("name").InnerText;
            var product = new Product(id, name);
            //Console.WriteLine($"Id: {id}, name: {name}");

            products.Add(product);

            using (var writer = new StreamWriter("C:\\Users\\Saint\\Desktop\\TaskRetail\\file.csv", false, Encoding.UTF8))
            using (var csv = new CsvWriter(writer, CultureInfo.InvariantCulture))
            {
                csv.WriteRecords(products);
            }

         var config = new CsvConfiguration(CultureInfo.InvariantCulture) { Delimiter = ",", PrepareHeaderForMatch = header => header.Header.ToLower() };
        using (var reader = new StreamReader("C:\\Users\\Saint\\Desktop\\TaskRetail\\file.csv", Encoding.UTF8))
        using (var csv = new CsvReader(reader, config))

        {
            var records = csv.GetRecords<Product>();

            foreach (var record in records)
            {
                Console.WriteLine($"{record.Id} {record.Name}");
            }
        }
    }
}

}

在此处输入图片说明

Because GetRecords() does return an object of type IEnumerable , you have to iterate over your records to print each one of them:

foreach(var record in records)
{
   Console.WriteLine($"{record.Id} {record.Name}");
}

Furthermore you have to access each property you want to print individually. Another option would be to override the ToString() method in your Product class.

EDIT

The initial problem wasn't the correct printing of the values but the parsing of the file as I learned from this comment:

CsvHelper.HeaderValidationException: 'Header with name 'id'[0] was not found. Header with name 'name'[0] was not found.

To tackle this problem one have to make sure that the delimiter character is set correctly. This can be enforced in the config object of the CsvHelper. Furthermore to avoid casing errors the configuration can be set to ignore the casing of the headers:

var config = new CsvConfiguration(CultureInfo.InvariantCulture) 
{ 
   Delimiter = ",", // Enforce ',' as delimiter
   PrepareHeaderForMatch = header => header.Header.ToLower() // Ignore casing
};

using (var csv = new CsvReader(reader, config))
{
   ...
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM