如何验证csv文件?

时间:2010-03-15 20:42:37

标签: php csv

我们如何验证CSV文件?

我有一个结构的CSV文件:

Date;Id;Shown
15-Mar-10;231;345
15-Mar-10;232;346
and so on and on !!! approx around 80,000 rows. 

如何在使用fgetcsv开始解析之前验证此CSV文件?

4 个答案:

答案 0 :(得分:21)

我不会尝试先验证文件:我宁愿一行一行地处理它,分别处理每一行:

  • 阅读一行
  • 验证没问题
  • 使用数据
  • 并转到下一行。


现在,什么可以“验证它没问题”意味着什么?

  • 至少:确保我可以将这行显示为CSV,使用我正常的函数集(也许是fgetcsv,也许是我的项目特有的其他功能 - 无论如何,如果我看不懂我的函数读取数百,这可能是因为该行存在问题)
  • 然后,检查字段数
  • 然后,对于每个字段,检查它是否包含“有效”数据
    • 是强制性的? optionnal?
    • 数字?
    • string?
    • 约会?
  • 然后,对于每个领域,进行一些更仔细的检查
    • 例如,对于“代码”字段:它是否对应于对我的应用程序合法的值?

如果一切顺利 - 好吧,没有更多的事要做,除了使用数据;-)
当你完成一行时,只需重复下一行。


当然,如果你想在做任何数据库(或类似的东西)之前接受或拒绝整个文件写,你将不得不:

  • 逐行解析文件,应用“验证”提示
  • 将每行的数据存储在内存中
  • 并且,当整个文件被读入内存时,
    • 要么开始使用数据
    • 或者,如果一行出错,请拒绝所有内容。


在您的特定情况下,您有三种字段:

Date;Id;Shown
15-Mar-10;231;345
15-Mar-10;232;346

根据我的猜测:

  • 第一个必须是约会
    • 使用一些正则表达式来验证这并不容易:每个月的天数不同,有很多个月,2月份的天数不一样,具体取决于年份,......
    • 在这种情况下,我可能会尝试用strtotime 之类的东西解析日期(不确定它对你正在使用的格式是否合适)
    • 或者我只是explode字符串
      • 确保有三个部分
      • 第三个是2位数
      • 第二个是JanFebMar,...
      • 之一
      • 第一个对应于正确的天数,具体取决于其他两个
  • 第二个:
    • 必须是整数
    • 必须是数据库中存在的有效值吗?
      • 如果是这样,一个简单的SQL查询将允许您检查
  • 对于第三个,不太确定......
    • 我猜它必须是一个整数?

答案 1 :(得分:0)

您可以使用正则表达式查找匹配的行(因此标记不匹配的行)。看看this link。话虽这么说,你需要阅读整个文件才能验证它,这样你最好只是在第一次尝试解析它并捕获任何错误。

答案 2 :(得分:0)

期望您正在阅读的数据有效,只需忽略任何看似无效或格式不正确的行。

CSV用于数据交换或数据存储。因此,生成文件时很可能已经“有效”。如果您 - 无论出于何种原因 - 将CSV文件作为用户输入(唯一可以来自无效或意外数据的真实来源),忽略该数据并告知用户无效行没有问题。

答案 3 :(得分:0)

我编写了一个开源Python工具,以简化http://pypi.python.org/pypi/cutplace/提供的此类文件的验证。

基本思想是使用OpenOffice.org,Excel或纯CSV在结构化界面规范中描述数据格式。这可以在几分钟内完成,并且足够清晰,可以作为文档。我们使用它来验证每天大约200,000行的文件。

您可以使用命令行验证CSV文件:

cutplace specification.csv data.csv

如果找到无效数据行,则退出代码为1.如果需要更多控制,可以编写一个Python脚本来导入cutplace模块并为验证事件添加侦听器。

例如,这里有一个规范可以验证您提供的样本数据,通过做一些假设填补您的简短描述的空白。 (我在这篇文章中用CSV编写规范。在实践中我更喜欢OpenOffice.org的Calc和ODS,因为我可以使用更多的格式化并使其更易于阅读和维护。)

,"Interface: Show statistics"
,
,"Data format"
"D","Format","CSV"
"D","Item delimiter",";"
"D","Header","1"
"D","Encoding","ASCII"
,
,"Fields"
,"Name","Example","Empty","Length","Type","Rule"
"F","date","15-Mar-10",,,"RegEx","\d\d-[A-Z][a-z][a-z]-\d\d"
"F","id","231",,,"Integer","0:"
"F","shown","345",,,"Integer","0:"
,
,"Checks"
,"Description","Type","Rule"
"C","id per date must be unique","IsUnique","date, id"

以“D”开头的行描述基本数据格式。在这种情况下,它是一个使用“;”的CSV文件作为ASCII编码中带有1个标题行的分隔符。

以“F”开头的行描述了各个字段。例如,

,"Name","Example","Empty","Length","Type","Rule"
"F","id","231",,,"Integer","0:"

定义Integer类型的必需字段“id”,其值为0或更大。要允许该字段为空,请在“空”列中指定“X”:

,"Name","Example","Empty","Length","Type","Rule"
"F","id","231","X",,"Integer","0:"

最后,有一个可选部分包含产生整个文件的更多预先检查,而不仅仅是单行。例如,如果文件中的每个日期必须仅为id提供一次日期,则可以使用以下命令说明:

,"Description","Type","Rule"
"C","id per date must be unique","IsUnique","date, id"

以空列开头的任何行都可以包含您喜欢的任何文本,并且在验证期间不会处理。这对标题,注释等很有用。