简体   繁体   English

C# Winforms - 读取 csv 文件时出现问题

[英]C# Winforms - Issue reading a csv file

I have looked at all of the csv reading examples I can find and I'm not quite sure where I'm going wrong with this one.我查看了我能找到的所有 csv 阅读示例,但我不太确定我在哪里出错了。

I am fairly new to C# but loving it so far!我对 C# 相当陌生,但到目前为止我很喜欢它!

Anyway heres the code that works great most of the time (you can see by the comments I have tried a bunch of different options in the read):无论如何,这是大部分时间都运行良好的代码(您可以通过评论看到我在阅读中尝试了一堆不同的选项):

StreamReader sr = new StreamReader(csvFileToImport);
                while (sr.EndOfStream != true)
                {
                    string line = sr.ReadLine();
                //string[] value = line.Split(new string[] { "\",\"" }, StringSplitOptions.None);
                //string[] value = line.Split(new string[] {","}, StringSplitOptions.None);
                //string[] value = line.Split(new string[] { "(?=(?:[^']*'[^']*')*[^']*$)" }, StringSplitOptions.None);
                //string[] value = line.Split(new string[] { "," }, StringSplitOptions.None);
                string[] value = Regex.Split(line, @"\s|[,]");

                StockItem si = new StockItem();
                    switch (stockFile.Supplier)
                    {
                        case "Leader":
                            si.Supplier = stockFile.Supplier;
                            si.Category = value[2].Replace("'", "''");
                            si.StockCode = value[11].Replace("'", "''");
                            si.Cost = Convert.ToDecimal(value[7]);
                            si.Description = value[4].Replace("'", "''");
                            si.Image = value[9].Replace("'", "''");
                            si.Manufacturer = value[10].Replace("'", "''");
                            si.Sell = Convert.ToDecimal(value[8]);
                            si.StockAdelaide = value[17].Replace("'", "''");
                            si.StockBrisbane = value[18].Replace("'", "''");

                            si.StockMelbourne = value[19].Replace("'", "''");
                            si.StockPerth = value[20].Replace("'", "''");
                            si.StockSydney = value[21].Replace("'", "''");
                            si.Subcategory = value[3].Replace("'", "''");

                            //Add line into db
                            string sql = "insert into Stock (Supplier, StockCode, Manufacturer, Category, Subcategory, Description, Cost, Sell, Image, StockPerth, StockAdelaide, StockSydney, StockBrisbane, StockMelbourne) values ('" + si.Supplier + "', '" + si.StockCode + "', '" + si.Manufacturer + "', '" + si.Category + "', '" + si.Subcategory + "', '" + si.Description + "', " + si.Cost + ", " + si.Sell + ", '" + si.Image + "', '" + si.StockPerth + "', '" + si.StockAdelaide + "', '" + si.StockSydney + "', '" + si.StockBrisbane + "', '" + si.StockMelbourne + "')";
                            cmd = new SqlCommand(sql, cn);
                            cmd.ExecuteNonQuery();
                            break;
                        default:
                            break;
                    }
                }
                success = true;
                cn.Close();

I have linked to a 1 line csv file which doesnt read correctly if anyone wouyld be so good as to have a look I would be really greatful!我已经链接到一个 1 行 csv 文件,如果有人愿意看一看我会非常感激,该文件无法正确读取!

Thanks in advance, and also feel free to point out any general code I could improve... I'm sure there is lots to improve on.在此先感谢,并随时指出我可以改进的任何通用代码......我相信有很多需要改进的地方。

Thanks again:)再次感谢:)

CSV Link: https://www.dropbox.com/s/nnaruu0twds3wrl/csv_error.csv?dl=0 CSV 链接: https://www.dropbox.com/s/nnaruu0twds3wrl/csv_error.csv?dl=0

UPDATE:更新:

Apologies for the lack of clarity, as I am reading the file I get the following error:为缺乏清晰度而道歉,当我阅读文件时,我收到以下错误:

System.FormatException: 'Input string was not in a correct format.' System.FormatException: '输入字符串的格式不正确。'

The line reads as:该行内容如下:

"MECMD4VL2X426,ME,Memory,DDR-4 (Desktop),Corsair Vengeance LPX 8GB (2x4GB) DDR4 2666MHz C16 Desktop Gaming Memory Black,\"Corsair 8GB (2x4GB) DDR4 2666MHz Vengeance LPX Black"

When I query the array it shows the values as:当我查询数组时,它显示的值如下:

value[0] "MECMD4VL2X426"
value[1] "ME"
value[2] "Memory"
value[3] "DDR-4"
value[4] "(Desktop)"
value[5] "Corsair"
value[6] "Vengeance"
value[7] "LPX"
...

It appears to get stuck on the brackets (that should be read into value[3]), and then starts seperating on space instead of comma.它似乎卡在括号上(应该读入 value[3]),然后开始用空格而不是逗号分隔。

Im happy to use a 3rd party csv reader if needed, however I'd love to understand how it works myself.如果需要,我很乐意使用第 3 方 csv 阅读器,但我很想了解它自己的工作原理。

Reading the csv you use string line = sr.ReadLine();读取 csv 您使用string line = sr.ReadLine(); but the RFC 4180 , 2.6 tell us that a field containig multiples lines should be encapsuled with DQuote " .但是RFC 4180 , 2.6 告诉我们包含多行的字段应该用 DQuote 封装"

So reading the file line by line will be an issue if those multiples lines field exist in your document.因此,如果文档中存在这些多行字段,则逐行读取文件将是一个问题。
I would drop the hand made regex and the ReadLine and use a more robust parser like CSV Helper .我会放弃手工制作的正则表达式和ReadLine并使用更强大的解析器,如CSV Helper

Then define the object you want to get from the CSV.然后定义你想从 CSV 得到的 object。

public class Leader
{
    public string LongColumn6 { get; set; }

    public string Supplier { get; set; }
    public string Category { get; set; }
    public string StockCode { get; set; }
    public Decimal Cost { get; set; }
    public string Description { get; set; }
    public string Image { get; set; }
    public string Manufacturer { get; set; }
    public Decimal Sell { get; set; }
    public string StockAdelaide { get; set; }
    public string StockBrisbane { get; set; }
    public string StockMelbourne { get; set; }
    public string StockPerth { get; set; }
    public string StockSydney { get; set; }
    public string Subcategory { get; set; }
}

And it's respective mapper: column & is Foo properties etc..它是各自的映射器:column & is Foo 属性等。

public sealed class LeaderMap : ClassMap<Leader>
{
    public LeaderMap()
    {
        Map(m => m.LongColumn6).Index(5); // the column that cause the issue

        //complete the List
        Map(m => m.Category).Index(2);
        Map(m => m.StockCode).Index(11);
        Map(m => m.Cost).Index(7);
        Map(m => m.Description).Index(4);
    }
}

Then the reading is simple:那么阅读就很简单了:

using (var csvReader = new CsvReader(reader,  CultureInfo.InvariantCulture ))
{   
    csvReader.Configuration.HasHeaderRecord = false;
    csvReader.Configuration.RegisterClassMap<LeaderMap>();
    records = csvReader.GetRecords<Leader>().ToList();
}

Note that in this live demo .请注意,在此现场演示中。 I used a StringReader in order to mimic a file Reader.我使用 StringReader 来模仿文件阅读器。
You can use a file reader and pass it your path.您可以使用文件阅读器并将其传递给您的路径。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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