8

I have .csv file with 4 columns. What's the easiest way to remove a line identical with the id of the first column? Here's where I got stuck:

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);
}

Unfortunately, databases were not a choice.

5 Answers 5

8
$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');
Sign up to request clarification or add additional context in comments.

Comments

3

I recently did a similar thing in for a newsletter unsubscription, heres my code:

$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;
}

this uses the temp file method of writing out the csv line by line to avoid memory errors. Then once the new file has been created, it deletes the original and renames the temp file.

You can modify this code so that it looks for an ID instead of an email address eg:

$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');

Comments

1
$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);
}

1 Comment

You are forgetting the part where you write out the csv array to another file. You also don't want to store the whole csv in an array becuause it could lead to out of memory errors. Better to write the csv out incrementally.
0

I have found a solution, that does not need to copy the file.

$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);
}

Note: only one of those fopen commands could fail, leaking the handle for the second one. It would be good, to check both handles independetly and close them on a error.

Comments

0

You can do:

$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;
    }
}

basically you run through each line and check if the id does NOT match the id sent in the get parameter, if it does not then it writes the line to the new container / variable.

And then rewrite the $new value to the file, this should work ok:

  • How big is the file
  • Do you have a CSV Header on line 0?

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.