不迭代 foreach 循环,但计数为 1849,应该迭代所有

发布于 2025-01-16 19:21:09 字数 1223 浏览 2 评论 0原文

我正在使用 CsvHelper 读取 CSV 文件。

这是我的代码(非常简单):

using (var reader = new StreamReader("example.csv"))
using (var csv = new CsvReader(reader, CultureInfo.InvariantCulture))
{
    var records = csv.GetRecords<CsvData>();
    int i = 0;
    foreach (var record in records)
    {                    
        i++;
        Console.WriteLine($"Processed {i}/{records.Count()} records."); 
    }
}
Console.WriteLine("Script finished");

问题是我的代码没有循环 foreach,所以它不会打印任何内容...我在 i++; 行中放置了一个断点,但它没有t 中断。

如果我打印 records.Count() 它将返回 3:

在此处输入图像描述

这可能是 CSV 文件的示例:

在此处输入图像描述

代码格式,以便您可以复制它:

Size,Color
8,Yellow
2,Orange
13,Blue

这可能是 CsvData 类的示例:

public class CsvData
{        
    public decimal? Size { get; set; }
    public string Color { get; set; }
}

如何将我的行解析迭代到我的 CsvData 类中,创建一个List 或类似的?

I'm using CsvHelper to read a CSV file.

This is my code (pretty simple):

using (var reader = new StreamReader("example.csv"))
using (var csv = new CsvReader(reader, CultureInfo.InvariantCulture))
{
    var records = csv.GetRecords<CsvData>();
    int i = 0;
    foreach (var record in records)
    {                    
        i++;
        Console.WriteLine(
quot;Processed {i}/{records.Count()} records."); 
    }
}
Console.WriteLine("Script finished");

The problem is that my code is not looping that foreach, so it won't print anything... I put a breakpoint in i++; line but it doesn't breaks.

If I print records.Count() it will return 3:

enter image description here

This could be an example of a CSV file:

enter image description here

Code format so you can copy it:

Size,Color
8,Yellow
2,Orange
13,Blue

And this could be an example of class CsvData:

public class CsvData
{        
    public decimal? Size { get; set; }
    public string Color { get; set; }
}

How should I iterate my rows parsing into my CsvData class creating a List<CsvData> or similar?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

黄昏下泛黄的笔记 2025-01-23 19:21:09

@Joel Coehoorn 是正确的。一旦您调用 .Count(),您就告诉 CsvHelper 读取整个 CSV 文件以找出文件中有多少条记录。您现在位于数据流的末尾,并且没有更多记录可供读取。调用 .ToList() 会做同样的事情。它读取整个 CSV 文件,但这次它将记录保存到内存的 records 变量中。如果您的文件较小,这很好,但如果您的文件非常大,则可能会遇到内存问题。

根据入门说明

GetRecords 方法将返回一个 IEnumerable,该 IEnumerable 将生成记录。这意味着当您迭代记录时,一次仅返回一条记录。这也意味着只有文件的一小部分被读入内存。不过要小心。如果您执行任何执行 LINQ 投影的操作,例如调用 .ToList(),整个文件将被读入内存。 CsvReader 仅向前,因此如果您想对数据运行任何 LINQ 查询,则必须将整个文件拉入内存。只要知道这就是你正在做的事情即可。

选项 1

您已经发现可以调用 ListRecords = csv.GetRecords().ToList(); 并将所有记录放入内存中。只要明白这就是你正在做的事情。我还将您的计数放入变量 var count =records.count();,而不是让您的代码每次循环通过 List 来获取计数。

选项 2

不要一开始就获取计数。最后只给出总数即可。

选项 3

循环文件两次。一次获取计数,第二次获取数据。

void Main()
{
    var count = 0;

    using (var reader = new StreamReader("example.csv"))
    using (var csv = new CsvReader(reader, CultureInfo.InvariantCulture))
    {
        count = csv.GetRecords<CsvData>().Count();
    }
    
    using (var reader = new StreamReader("example.csv"))
    using (var csv = new CsvReader(reader, CultureInfo.InvariantCulture))
    {
        var records = csv.GetRecords<CsvData>();
        int i = 0;
        foreach (var record in records)
        {
            i++;
            Console.WriteLine($"Processed {i}/{count} records.");
        }
    }
}

public class CsvData
{
    public int Size { get; set; }
    public string Color { get; set; }
}

@Joel Coehoorn is correct. As soon as you call .Count(), you have just told CsvHelper to read the whole CSV file in order to find out how many records there are in the file. You are now at the end of the data stream and there are no more records left to read. Calling .ToList() does the same thing. It reads the whole CSV file, but this time it saves the records to memory in the records variable. This is fine if your file is smaller, but you could run into memory issues if you have a very large file.

Per the Getting Started Instructions

The GetRecords<T> method will return an IEnumerable<T> that will yield records. What this means is that only a single record is returned at a time as you iterate the records. That also means that only a small portion of the file is read into memory. Be careful though. If you do anything that executes a LINQ projection, such as calling .ToList(), the entire file will be read into memory. CsvReader is forward only, so if you want to run any LINQ queries against your data, you'll have to pull the whole file into memory. Just know that is what you're doing.

Option 1

You have already discovered that you can call List<CsvData> records = csv.GetRecords<CsvData>().ToList(); and bring all the records into memory. Just understand that is what you are doing. I would also put your count into a variable var count = records.count(); instead of making your code loop through the List<CsvData> each time to get the count.

Option 2

Don't get the count at the beginning. Just give a total at the end.

Option 3

Loop through the file twice. Once to get the count and the 2nd time to get the data.

void Main()
{
    var count = 0;

    using (var reader = new StreamReader("example.csv"))
    using (var csv = new CsvReader(reader, CultureInfo.InvariantCulture))
    {
        count = csv.GetRecords<CsvData>().Count();
    }
    
    using (var reader = new StreamReader("example.csv"))
    using (var csv = new CsvReader(reader, CultureInfo.InvariantCulture))
    {
        var records = csv.GetRecords<CsvData>();
        int i = 0;
        foreach (var record in records)
        {
            i++;
            Console.WriteLine(
quot;Processed {i}/{count} records.");
        }
    }
}

public class CsvData
{
    public int Size { get; set; }
    public string Color { get; set; }
}
葬心 2025-01-23 19:21:09

将集合转换为列表有效:

在此处输入图像描述

只是:

List<CsvData> records = csv.GetRecords<CsvData>().ToList();

代码结果(适合懒人)

using (var reader = new StreamReader("example.csv"))
using (var csv = new CsvReader(reader, CultureInfo.InvariantCulture))
{
    var records = csv.GetRecords<CsvData>().ToList();
    int i = 0;
    foreach (var record in records)
    {                    
        i++;
        Console.WriteLine($"Processed {i}/{records.Count()} records."); 
    }
}
Console.WriteLine("Script finished");

Converting the collection to list worked:

enter image description here

Just by:

List<CsvData> records = csv.GetRecords<CsvData>().ToList();

Result of code (for lazy people)

using (var reader = new StreamReader("example.csv"))
using (var csv = new CsvReader(reader, CultureInfo.InvariantCulture))
{
    var records = csv.GetRecords<CsvData>().ToList();
    int i = 0;
    foreach (var record in records)
    {                    
        i++;
        Console.WriteLine(
quot;Processed {i}/{records.Count()} records."); 
    }
}
Console.WriteLine("Script finished");
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文