使用PHP,如果ID列重复,如何删除CSV行?

使用PHP,如果ID列重复,如何删除CSV行?,php,csv,Php,Csv,我的目标是使用PHP,如果重复值出现在特定列中,则删除CSV文件的整行,在本例中为ID列。我自然希望保留显示重复ID的第一行(参见下面的示例) 我不想创建新的CSV文件,我想打开该文件,删除需要删除的内容,然后覆盖当前文件 我还想存储变量中已删除的行数 输入(注意重复ID为3):file.csv 预期输出:file.csv 然后还能:echo$removedRows将输出:1 如何做到这一点 我已设法将其保存到新文件中,但我只想覆盖当前文件,我不知道为什么会出现“环绕名称”列: ID,Date

我的目标是使用PHP,如果重复值出现在特定列中,则删除CSV文件的整行,在本例中为ID列。我自然希望保留显示重复ID的第一行(参见下面的示例)

我不想创建新的CSV文件,我想打开该文件,删除需要删除的内容,然后覆盖当前文件

我还想存储变量中已删除的行数

输入(注意重复ID为3):file.csv 预期输出:file.csv 然后还能:
echo$removedRows将输出:1
如何做到这一点


我已设法将其保存到新文件中,但我只想覆盖当前文件,我不知道为什么会出现“环绕名称”列:

ID,Date,Name,Age
1,12/3/13,"John Doe ",23
2,12/3/19,"Jane Doe ",21
3,12/4/19,"Jane Doe ",19
4,12/3/19,"Jane Doe ",21
使用以下代码:
$input_filename = 'file.csv';

// Move the csv-file to 'newfile' directory
copy($input_filename, 'newfile/'.$input_filename);

$output_filename = 'newfile/'.$input_filename;

$input_file = fopen($input_filename, 'r');
$output_file = fopen($output_filename, 'w');

$IDs = array();

// Read the header
$headers = fgetcsv($input_file, 1000);
fputcsv($output_file, $headers);

// Flip it so it becomes name => ID
$headers = array_flip($headers);

// Read every row
while (($row = fgetcsv($input_file, 1000)) !== FALSE)
{
    $ID = $row[$headers['ID']];
    // Do we already have this ID?
    if (isset($IDs[$ID]))
        continue;

    // Mark this ID as being found
    $IDs[$ID] = true;
    // Write it to the output
    fputcsv($output_file, $row);
}

由于您不能同时读取文件和写入文件,因此我建议您将数据写入另一个文件,然后将此文件移动到源文件,例如:

$input_filename = 'file.csv';
$output_filename = 'newfile/' . $input_filename;

// Copy the csv-file to 'newfile' directory
copy($input_filename, $output_filename);
$input_file = fopen($input_filename, 'r');
$output_file = fopen($output_filename, 'w');

$IDs = array();

// Read the header
$headers = fgetcsv($input_file, 1000);
fputcsv($output_file, $headers);

// Flip it so it becomes name => ID
$headers = array_flip($headers);

// Deleted rows counter
$rows_deleted = 0;
// Read every row
while (($row = fgetcsv($input_file, 1000)) !== FALSE)
{
    $ID = $row[$headers['ID']];
    // Do we already have this ID?
    if (isset($IDs[$ID])) {
        // row skipped - therefore it is deleted
        $rows_deleted++;
        continue;
    }

    // Mark this ID as being found
    $IDs[$ID] = true;
    // Write it to the output
    fputcsv($output_file, $row);
}

// Now we should move output file to input one
rename($output_filename, $input_filename);

echo "Deleted: " . $rows_deleted;
至于数据周围的
”——这是
fputcsv
的结果。这是出于安全原因。想象一下,如果您的数据不存在

3,12/4/19,Jane Doe ,19
但是

您想考虑<代码>简,DOE 作为一个元素。这就是为什么使用<代码> >语法分析器更清楚地对待您的行:

3,12/4/19,"Jane, Doe ",19    // here `Jane, Doe` is one element

通常,在
不影响解析生成的csv。但是如果您确定不需要引号-您可以传递更多引号,尽管我不确定它是否可以作为
附件
参数使用空值。

这是
我想要的
文本。我们这里需要问题。你试过什么吗?可能是一些代码?对不起,你是对的,已更新。文件是否总是按id排序?如果不是,它能有多大?是否还有其他内容试图在脚本运行的同时访问该文件?在这些问题没有答案的情况下,你的问题的解决方案是无效的。使用DBMS而不是文本文件来维护数据有很多原因,您可能需要考虑其中一些。空的包需要解决。类似这样的东西可以做:
fputs($output\u file,introde(',',$row).PHP\u EOL)工作完美!我之所以把这个附件放在这里,是因为显而易见的原因,感谢@u_mulder的演讲。有关于如何存储“删除了多少行”的建议吗?太棒了@u_mulder,非常感谢!关于如何将删除的行存储在数组中以便能够记录删除的行的任何建议?请在继续之前将它们添加到数组中
3,12/4/19,Jane Doe ,19
3,12/4/19,Jane, Doe ,19
3,12/4/19,"Jane, Doe ",19    // here `Jane, Doe` is one element