代码之家  ›  专栏  ›  技术社区  ›  cbednarski

自动检测文件中是否存在CSV标头

  •  19
  • cbednarski  · 技术社区  · 14 年前

    简短问题: 如何自动检测CSV文件的第一行是否有头?

    我正在尝试找出一种可靠的方法来自动检测CSV头的存在,这样脚本就可以决定是使用CSV文件的第一行作为键/列名,还是立即开始解析数据。因为我需要的只是一个布尔测试,所以我可以在自己检查CSV文件之后很容易地指定一个参数,但是我不想这样做(去自动化)。

    1. 由于某些原因,标头包含数字数据
    2. 前几行(或CSV的大部分)为空

    如果我能得到一个“最佳猜测”,并让解析器出错,或者在无法决定的情况下发出警告,那没关系。如果这在时间或计算上是非常昂贵的(而且花费的时间比它应该节省的要多),我会很高兴地放弃这个想法,继续从事“重要的事情”。

    我正在使用PHP,但这更像是一个算法/计算问题,而不是特定于实现的问题。如果有一个简单的算法我可以用,太好了。如果你能给我指出一些相关的理论/讨论,那也太好了。如果有一个巨大的库可以进行自然语言处理或300种不同的解析,我就不感兴趣了。

    6 回复  |  直到 14 年前
        1
  •  16
  •   Nick Johnson    14 年前

    正如其他人所指出的,你不可能100%可靠地做到这一点。不过,在某些情况下,获得“基本正确”的结果是有用的——例如,具有CSV导入功能的电子表格工具常常试图自己解决这个问题。这里有一些试探法,倾向于指出第一行 不是吗 标题:

    • 第一行的列并不都是唯一的
    • 第一行似乎包含日期或其他通用数据格式(例如,xx)
        2
  •  7
  •   frankc    14 年前


    姓名
    吉姆
    汤姆

    大多数csv阅读器都将hasHeader作为一个选项,并允许您根据需要传入自己的头文件。即使在您认为可以检测到的情况下,作为字符头和数字数据,您也可能会遇到灾难性的失败。如果你的专栏是宝马系列的列表呢?


    5

    您将无法正确处理此问题。最糟糕的是,你会失去最好的车!

        3
  •  2
  •   Asklepius M.D.    14 年前

    在纯粹抽象的意义上,我不认为你的问题有一个简单的算法答案,因为它归结为:“如果我对dataA和dataB一无所知,我如何区分它们?”。dataA和dataB总是有不可区分的可能性。也就是说,我会从简单开始,只在需要的时候增加复杂性。例如,如果检查前五行,对于给定的列(或多个列),如果第2-5行中的数据类型都相同,但与第1行中的数据类型不同,则很有可能存在标题行(增加的样本大小可减少出错的可能性)。这将(排序)解决#1/#3—如果所有行都已填充,但数据无法区分,则可能引发异常,以允许调用程序决定下一步要做什么。对于#2,只要不将一行计算为一行,除非并且直到它提取非空数据……这将在除空文件以外的所有文件中都有效(在这种情况下,您将点击EOF)。它永远不会是万无一失的,但它可能是“足够接近”。

        4
  •  1
  •   dmb    14 年前

    这实际上取决于你希望你的工具有多“通用”。如果数据总是数字的,那么只要假设非数字标题(这似乎是一个相当公平的假设),就很容易了。

    但除此之外,如果您还不知道数据中存在哪些模式,那么就无法提前对它们进行测试。

    FWIW,我实际上刚刚写了一个脚本,用于解析TSV中的一些内容,所有这些内容都来自同一个源。源代码处理头文件/格式的方法非常分散,因此在执行时只让脚本从命令行向我提问是有意义的(这是页眉吗?哪些列是重要的?)。所以没有自动化,但它让我可以快速浏览正在处理的数据集,而不是试图预测每个有趣的格式化案例。而且,我的答案保存在一个文件中,所以每个文件我只需要参与一次。不理想,但效率高。

        5
  •  1
  •   StevieD    5 年前

    本文提供了一些很好的指导:

    http://penndsg.com/blog/detect-headers/

        6
  •  0
  •   John Ballinger    10 年前

    如果你有这样的标题。

    1,约翰,john@john.com,2020年1月12日

    然后对标题行执行filter\u var(str,filter\u VALIDATE\u EMAIL)将失败。因为电子邮件地址只在数据行中。所以检查邮件地址的标题行(假设您的CSV中有电子邮件地址)。

    第二个主意。 http://php.net/manual/en/function.is-numeric.php

    如果您知道列中有日期,那么检查标题行中的日期也可以。

    显然,您需要知道您所期望的数据类型。我“期待”的电子邮件地址。