【问题标题】:C# Winforms - Issue reading a csv fileC# Winforms - 读取 csv 文件的问题
【发布时间】:2020-05-04 06:12:15
【问题描述】:

我查看了所有我能找到的 csv 阅读示例,但我不太确定我哪里出了问题。

我对 C# 还很陌生,但到目前为止我很喜欢它!

无论如何,这里的代码在大多数时间里都很好用(你可以通过 cmets 看到我在阅读中尝试了一堆不同的选项):

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();

我已经链接到一个 1 行的 csv 文件,如果有人愿意看一看我会非常感激,该文件无法正确读取!

在此先感谢,也请随时指出我可以改进的任何通用代码...我确信还有很多需要改进的地方。

再次感谢:)

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

更新:

抱歉,我在阅读文件时出现以下错误:

System.FormatException: '输入字符串的格式不正确。'

该行内容如下:

"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"

当我查询数组时,它显示的值如下:

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"
...

它似乎卡在括号上(应该读入 value[3]),然后开始用空格而不是逗号分隔。

如果需要,我很乐意使用第 3 方 csv 阅读器,但我很想了解它自己的工作原理。

【问题讨论】:

  • 它“无法正确读取” - 怎么样?您是否得到错误的列、跳过行、出现异常?请说明。
  • 另外,不要尝试转义引号来构建 sql 命令,而是使用参数。
  • 最简单的解决方案是 Imo 使用像 CSV helper 这样的第 3 方。你只需要定义类,3行代码就足够了。
  • “我已链接到 1 行 csv 文件”,如果它只有 1 行,请简单发布。我们不喜欢从未知来源下载东西。
  • Mong Zhu - 没错,我不想被空间分割。我将尝试拖放的解决方案 - 感谢大家的帮助

标签: c# csv streamreader


【解决方案1】:

阅读你使用string line = sr.ReadLine();但RFC 4180 的csv, 2.6告诉我们包含多行的字段应该用DQuote"封装。

因此,如果您的文档中存在这些多行字段,则逐行读取文件将是一个问题。
我会放弃手工制作的正则表达式和ReadLine,并使用更强大的解析器,如CSV Helper。

然后定义要从 CSV 中获取的对象。

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; }
}

它是各自的映射器: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);
    }
}

那么读法就简单了:

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

请注意,在此 live demo 中。 我使用 StringReader 来模拟文件阅读器。
您可以使用文件阅读器并将其传递给您的路径。

【讨论】:

  • 非常感谢您的全面回答 - 我会试一试并报告:)
猜你喜欢
  • 1970-01-01
  • 2015-09-30
  • 2019-03-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多