【问题标题】:Remove Line From CSV File从 CSV 文件中删除行
【发布时间】:2011-05-03 14:08:04
【问题描述】:

我有 4 列的 .csv 文件。删除与第一列的 id 相同的行的最简单方法是什么?这就是我卡住的地方:

if($_GET['id']) {
    $id = $_GET['id'];
    $file_handle = fopen("testimonials.csv", "rw");

    while (!feof($file_handle) ) {
        $line_of_text = fgetcsv($file_handle, 1024);    
        if ($id == $line_of_text[0]) {
            // remove row
        }
    }
    fclose($file_handle);
}

不幸的是,数据库不是一种选择。

【问题讨论】:

    标签: php csv fopen fgetcsv


    【解决方案1】:

    我找到了一个解决方案,不需要复制文件。

    $file = 'testimonials.csv'
    // open two handles on the same file
    $input = fopen($file ,'r'); // read mode
    $output = fopen($file, 'c'); // write mode
    
    if($input !== FALSE && $output !== FALSE) { // check for error
        while (($data = fgetcsv($input, $CSVLIMIT, $sep)) !== FALSE) {
            if(reset(data) == $id) {
                continue;
            }
            fputcsv($output, $data, $sep);
        }
    
        // close read handle
        fclose($input);
        // shorten file to remove overhead created by this procedure
        ftruncate($output, ftell($output));
        fclose($output);
    }
    

    注意:这些 fopen 命令中只有一个可能会失败,从而泄漏第二个的句柄。最好独立检查两个句柄并在出现错误时关闭它们。

    【讨论】:

      【解决方案2】:
      $table = fopen('table.csv','r');
      $temp_table = fopen('table_temp.csv','w');
      
      $id = 'something' // the name of the column you're looking for
      
      while (($data = fgetcsv($table, 1000)) !== FALSE){
          if(reset($data) == $id){ // this is if you need the first column in a row
              continue;
          }
          fputcsv($temp_table,$data);
      }
      fclose($table);
      fclose($temp_table);
      rename('table_temp.csv','table.csv');
      

      【讨论】:

        【解决方案3】:

        我最近为取消订阅时事通讯做了类似的事情,这是我的代码:

        $signupsFile = 'newsletters/signups.csv';
        $signupsTempFile = 'newsletters/signups_temp.csv';
        $GLOBALS["signupsFile"] = $signupsFile;
        $GLOBALS["signupsTempFile"] = $signupsTempFile;
        
        
        function removeEmail($email){
            $removed = false;
            $fptemp = fopen($GLOBALS["signupsTempFile"], "a+");
            if (($handle = fopen($GLOBALS["signupsFile"], "r")) !== FALSE) {
                while (($data = fgetcsv($handle)) !== FALSE) {
                if ($email != $data[0] ){
                    $list = array($data);
                    fputcsv($fptemp, $list);
                    $removed = true;
                }
            }
            fclose($handle);
            fclose($fptemp);
            unlink($GLOBALS["signupsFile"]);
            rename($GLOBALS["signupsTempFile"], $GLOBALS["signupsFile"]);
            return $removed;
        }
        

        这使用临时文件方法逐行写出 csv 以避免内存错误。然后,一旦创建了新文件,它就会删除原始文件并重命名临时文件。

        您可以修改此代码,使其查找 ID 而不是电子邮件地址,例如:

        $id = $_GET['id'];  
        $fptemp = fopen('testimonials-temp.csv', "a+");
        if (($handle = fopen('testimonials.csv', "r")) !== FALSE) {
            while (($id= fgetcsv($handle)) !== FALSE) {
            if ($id != $data[0] ){
                $list = array($data);
                fputcsv($fptemp, $list);
            }
        }
        fclose($handle);
        fclose($fptemp);
        unlink('testimonials.csv');
        rename('testimonials-temp.csv','testimonials.csv');
        

        【讨论】:

          【解决方案4】:
          $id = $_GET['id'];
          if($id) {
              $file_handle = fopen("testimonials.csv", "w+");
              $myCsv = array();
              while (!feof($file_handle) ) {
                  $line_of_text = fgetcsv($file_handle, 1024);    
                  if ($id != $line_of_text[0]) {
                      fputcsv($file_handle, $line_of_text);
                  }
              }
              fclose($file_handle);
          }
          

          【讨论】:

          • 您忘记了将 csv 数组写入另一个文件的部分。您也不想将整个 csv 存储在一个数组中,因为它可能导致内存不足错误。最好以增量方式写出 csv。
          【解决方案5】:

          你可以这样做:

          $new = '';
          while (!feof($file_handle))
          {
              $line_of_text = fgetcsv($file_handle, 1024);    
              if ($id != $line_of_text[0])
              {
                   $new .= implode(',',$line_of_text) . PHP_EOL;
              }
          }
          

          基本上你运行抛出每一行并检查 id 是否 NOT 与 get 参数中发送的 id 匹配,如果匹配 not 然后它将该行写入新容器/变量。

          然后将$new 值重写到文件中,这应该可以正常工作:

          • 文件有多大
          • 0 线上有 CSV 标头吗?

          【讨论】:

            猜你喜欢
            • 2020-07-18
            • 2018-08-15
            • 2020-12-17
            • 2020-09-11
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多