首页 > 解决方案 > 如何在 C# 中正确获取 csv 文件头?相同的代码得到不同的结果

问题描述

我想从 csv 文件中提取标题数据(要清楚:我的意思是包含列名的文件的第一行)(我从其他帖子中看到 FileHelpers 应该是好的,但在我的万一这不是一个选项...)它可以工作,但我仍然有问题。

我想读取具有以下格式的文件(抱歉格式错误,我不知道如何在这里使它更漂亮):

header1,header2,header3
data1,data2,data3

我正在使用以下代码来实现这一点:

string [] csvHeader;
using (CsvReader csv = new CsvReader(file.OpenText(), true, ','))
{
   if (!csv.GetFieldHeaders().Any())
       throw new Exception("header of file empty \n" + file.FullName);
                                    
   csvHeader = csv.GetFieldHeaders()[0].ToString().Split(',');
   if (!CompareArrays(csvHeader, expHeaderFormat))
       throw new MalformedCsvException("Csv Headers don't match! \n CsvHeader: " + csvHeader.ToString() + "\n Expected format: " + expHeaderFormat.ToString());
}

现在我的问题:

  1. 为什么在检索标头时需要获取第一个元素“[0]”?这对我来说没有意义。

    1. 仅适用于我的一个文件,当在另一个文件上尝试它时,它的格式完全相同(在我看来),所有的突然,当我访问 [0] 时,我得到了标题的第一个元素。这是我所期望的行为,但现在由于某种原因我无法读出整个标题。
  2. 为什么不能只执行以下操作来检索整个第一行,因为根据文档“GetFieldHeaders()”返回一个字符串数组,所以这对我来说很有意义:

    csvHeader =csv.GetFieldHeaders().ToString().Split(',');
    

我希望足以继续解决我的问题......

编辑:我正在使用以下库

using CsvFile;
using LumenWorks.Framework.IO.Csv;

标签: c#csvfilereader

解决方案


Lumenworks Csv的codeproject 文档注意到该库现在已经过时了,但它仍然可以与那里的示例代码一起使用:

using System.IO;
using LumenWorks.Framework.IO.Csv;
void ReadCsv()
{
    // open the file "data.csv" which is a CSV file with headers
    using (CsvReader csv =
           new CsvReader(new StreamReader("data.csv"), true))
    {
        int fieldCount = csv.FieldCount;

        string[] headers = csv.GetFieldHeaders();
        while (csv.ReadNextRecord())
        {
            for (int i = 0; i < fieldCount; i++)
                Console.Write(string.Format("{0} = {1};",
                              headers[i], csv[i]));
            Console.WriteLine();
        }
    }
}

为什么在检索标头时需要获取第一个元素“[0]”?这对我来说没有意义。

关于文件的整个第一行如何进入数组 0 的评论中有一些喋喋不休。我不确定这是怎么可能的,因为:

  • 您已将文件示例粘贴到问题中,并且它确实包含逗号
  • csv代表逗号分隔值
  • csv阅读器默认使用逗号作为分隔符

我预见到 csv 阅读器不会在逗号上分割第一行的唯一方法是:

  • 第一行以 " 或其他引号字符开头,因此被视为单个值 -> 文件已损坏,修复文件或更改阅读器使用的引号字符
  • 该文件不使用真正的 ascii 逗号作为分隔符,但可能使用其他一些看起来像逗号的 Unicode 字符;修复文件或向读者指定实际的分隔符
  • 默认情况下,阅读器库不会以逗号分隔(难以置信),因此请在 csv 阅读器的构造函数中指定逗号,在 True 之后

仅适用于我的一个文件,当在另一个文件上尝试它时,它的格式完全相同(在我看来),所有的突然,当我访问 [0] 时,我得到了标题的第一个元素。这是我所期望的行为,但现在由于某种原因我无法读出整个标题。

您需要向我们展示这些文件的屏幕截图,在十六进制编辑器中打开,以便我们告诉您。这将是我上面给出的原因之一。现在我们得到的只是你说文件在你看来是一样的;向我们展示真实文件,以便我们可以独立进行评估

你抱怨你不能得到所有的标题,但如果你只用 [0] 选择第一个标题,你永远不会得到 - 库正在返回所有标题,你选择只记住一个并扔掉其余的

您正在编写不需要的奇怪调试代码、比较数组等;所有这些检查都可以在调试器中完成,使用我在上面发布的代码,该代码是由编写库的人编写的 - 这是正确的

您正在从一些示例站点中提取代码片段,这些代码是由具有不同场景的不同人编写的代码,并且不能保证与您的场景等效 - 它们可能会在选项卡上拆分,或者有奇怪的引号字符等。你看不到他们正在阅读的文件,只有他们编写的代码。我们应该放弃所有这些并查看您正在阅读的文件并使其适合您的场景,而不是他们的

为什么不能只执行以下操作来检索整个第一行,因为根据文档“GetFieldHeaders()”返回一个字符串数组,所以这对我来说很有意义:

csvHeader =csv.GetFieldHeaders().ToString().Split(',');

因为这在周日的一个月里永远不会奏效。GetFieldHeaders 返回作为标题的字符串数组。对字符串数组调用 ToString 会给出对象的类型,在本例中为“System.String[]”,它不包含标题和逗号,因此将其拆分为逗号是完全没用的,而且是错误的做法!


推荐阅读