使用PHP计算CSV文件中的列数


Count number of columns in a CSV file, using PHP?

在将文本文件的数据转储到MYSQL数据库之前,是否可以对其进行验证?

我想检查它是否包含,比如说,5列(数据)。如果是,那么我继续进行以下查询:

LOAD DATA CONCURRENT INFILE 'c:/test/test.txt' 
INTO TABLE DUMP_TABLE FIELDS TERMINATED BY ''t' ENCLOSED BY '' LINES TERMINATED BY ''n' ignore 1 lines.

如果没有,我会删除整行。我对txt文件中的所有行重复此过程。

文本文件包含以下格式的数据:

id  col2    col3    2012-07-27-19:27:06 col5
id  col2    col3    2012-07-25-09:58:50 col5
id  col2    col3    2012-07-23-10:14:13 col5

EDIT:阅读您的评论后,以下是在制表符分隔的数据上执行相同操作的代码:

$handler = fopen("myfile.txt","r");
$error = false;
while (!feof($handler)){
   fgets($handler,$linetocheck);
   $cols = explode (chr(9), $linetocheck); //edit: using http://es.php.net/manual/en/function.fgetcsv.php you can get the same result as with fgets+explode
   if (count($cols)>$max_cols){
       $error=true;
       break;
   }
}
fclose($handler);
if (!$error){
    //...do stuff
}

这段代码逐行读取一个文件,比如"myfile.txt",如果其中任何一行的长度超过$max_cols,则将变量$error设置为true。(如果你不是这么问的,我很抱歉,你的问题对我来说不是最清楚的)

$handler = fopen("myfile.txt","r");
$error = false;
while (!feof($handler)){
   fgets($handler,$linetocheck);
   if (strlen($linetocheck)>$max_cols){
       $error=true;
       break;
   }
}
fclose($handler);
if (!$error){
    //...do stuff
}

我知道这是一个老话题,但我自己也在寻找类似的东西,我遇到了这个话题,但这里提供的答案都没有帮助我。

因此,我提出了自己的解决方案,经过测试,效果非常好(可以改进)。

假设我们有一个名为example.csv的CSV文件,其中包含以下伪数据(有意地,最后一行第6行包含一个额外的数据,然后是其他行):

Name,Country,Age
John,Ireland,18
Ted,USA,22
Lisa,UK,23
Michael,USA,20
Louise,Ireland,22,11

现在,当我们检查CSV文件以确保所有行都有相同数量的数据时,下面的代码块将完成任务并指出错误发生的行:

    function validateCsvColumnLength($pathToCsvFile)
    {
        if(!file_exists($pathToCsvFile) || !is_readable($pathToCsvFile)){
            throw new 'Exception('Filename doesn`t exist or is not readable.');
        }
        if (!$handle = fopen($pathToCsvFile, "r")) {
            throw new 'Exception("Stream error");
        }
        $rowLength       = [];
        $rowNumber       = 0;
        while (($data    = fgetcsv($handle)) !== FALSE) {
            $rowLength[] = count($data);
            $rowNumber++;
        }
        fclose($handle);
        $rowKeyWithError   = array_search(max($rowLength), $rowLength);
        $differentRowCount = count(array_unique($rowLength));
        // if there's a row that has more or less data, throw an error with the line that triggered it
        if ($differentRowCount !== 1) {
            throw new 'Exception("Error, data count from row {$rowKeyWithError} does not match header size");
        }
        return true;
    }

要真正测试它,只需执行var_dump()即可查看结果:

   var_dump(validateCsvColumnLength('example.csv'));

您的意思是什么列?如果只是指行中的字符数,只需将文件拆分(explode)为多行,并检查它们的长度是否等于5。

如果你指的是带有delimeter的列,那么你应该在每行中找到该拆分器的出现次数,然后再次检查它们是否等于5。对该使用fgetcsv

我假设您谈论的是文件中每一行的长度。如果是这样,这里有一个可能的解决方案。

$file_handle = fopen("myfile", "r");
while (!feof($file_handle)) {
   $line = fgets($file_handle);
   if(strlen($line)!=5) {
       throw new Exception("Could not save file to database.");
       break;
   }
}
fclose($file_handle);

是的,这是可能的。我已经做了那件事。使用PHP的csv处理函数。

您将需要这些功能:

fopen()fgetcsv()

可能还有其他一些。

fgetcsv返回一个数组。

我将给您一个如何验证的简短示例。

这是csv:col1、col2、col3、col41,2,3,41,2,3,4,1,2,3,4,51,2,3,4

我将跳过fopen部分,直接进入验证步骤。请注意,"''t"是制表符。

$row_length;
$i = 0;
while($row = fgetcsv($handle,0,"'t") {
  if($i == 0) {
    $row_length = sizeof($row);
  } else {
    if(sizeof($row) != $row_length) {
      echo "Error, line $i of the data does not match header size";
      break;
    }
  }
}

这将测试每一行,以确保它与第一行($i=0)的长度相同。

编辑:如果你不知道如何搜索互联网,这里是fgetcsv的页面:http://php.net/manual/en/function.fgetcsv.php

以下是功能原型:数组fgetcsv(resource$handle[,int$length=0[,string$delimiter=','[,stringe$enclosure='"'[,string$escape='''']]])

正如您所看到的,在将数据发送到LOAD data in FILE之前,它提供了在PHP中进行快速扫描所需的一切。

我已经在自己的程序中解决了你的确切问题。我的程序还自动消除了重复的行和其他很酷的东西。

您可以尝试看看fgetcsv是否足够。如果没有,请对你所说的列的含义进行更多的描述。