【问题标题】:How to properly get csv file header in c#? Getting different results for same code如何在 C# 中正确获取 csv 文件头?相同的代码得到不同的结果
【发布时间】:2020-07-03 06:48:15
【问题描述】:

我想从 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;

【问题讨论】:

  • 你想要一个数组还是字符串?
  • 我正在尝试将标题字段保存到我的字符串数组中
  • csvHeader = csv.GetFieldHeaders(); ?我不确定您使用的是什么库,但是 GetFieldHeaders 方法返回一个列表或数组或其他东西是有意义的。只要分配它,如果它是某种其他类型的IEnumerable 调用.GetFieldHeaders().ToArray()
  • 你正在使用的这个库的文档在哪里?
  • 我的猜测是这个库正在寻找一个不同于, 的分隔符。也许你应该试试 CsvHelper 库,至少它很容易找到它的文档

标签: c# csv filereader


【解决方案1】:

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

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]”?这对我来说没有意义。

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

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

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

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

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

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

您抱怨您无法获取所有标题,但如果您只选择带有 [0] 的第一个标题,则永远不会 - 库正在返回所有标题,您选择只记住一个并丢弃其余标题

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

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

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

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

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

【讨论】:

  • 感谢您的详尽回答并指出,图书馆有些过时了!我将在星期一再次使用公司笔记本电脑时尝试更新问题并尝试您的建议。没错,如果没有更多信息,您需要相信我的文件格式相同。会努力更新的!我已经在构造函数中添加','作为分隔符的部分,我相当确定其他错误点也不是这种情况,但只有在再次检查后才会知道。
  • 没有问题;不要忘记向我们发布在 hex 编辑器(例如 HxD)中打开的 csv 文件的屏幕截图。我通常要求文件的十六进制转储,因为它们显示不可见的东西,如字节顺序标记和其他可能混淆解析器的东西 - 如果你打开一个 csv 文件,你不一定会看到这些东西。记事本并粘贴您看到的内容;十六进制编辑器的屏幕截图确实是查看数据的所有方式,我们可以将它与 lumenworks 的代码结合使用,看看是否有任何问题
猜你喜欢
  • 2021-02-17
  • 1970-01-01
  • 1970-01-01
  • 2019-08-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多