如何使用PHP删除文本文件中的单行

4

我想知道是否可以使用PHP删除文本文件中的单行。

我将电子邮件地址存储在名为databse-email.txt的平面文本文件中。

我使用以下代码:

<?php
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
   $email = $_POST['email-subscribe'] . ',' . "\n";
   $store = file_put_contents('database-email.txt', $email, FILE_APPEND | LOCK_EX);
   if($store === false) {
     die('There was an error writing to this file');
   }
   else {
     echo "$email successfully added!";
   }
}

?>

表单:

<form action="" method="POST">
   <input name="email-subscribe" type="text" />
   <input type="submit" name="submit" value="Subscribe">
</form>

文件内容如下:
janny@live.nl,
francis@live.nl,
harry@hotmail.com,
olga@live.nl,
annelore@mail.ru,
igor@gmx.de,
natasha@hotmail.com,
janny.verlinden@gmail.com,

所有行都是用,分隔的。
假设我只想删除电子邮件地址:igor@gmx.de,我该怎么做呢?
我想实现一个退订表单,并删除.txt文件中的一行。

3
为了避免多个用户同时修改相同的内容,我不会使用文本文件,而是使用数据库表。使用数据库表可以更轻松地预防这种情况。 - Erik Kalkoken
5个回答

5
你可以使用 str_replace 函数。
$content = file_get_contents('database-email.txt');
$content = str_replace('igor@gmx.de,', '', $content);
file_put_contents('database-email.txt', $content);

3

由于文件系统的工作方式,你无法以一种直观的方式完成此操作。你需要覆盖文件,并删除其中除了你想要删除的行之外的所有行。以下是一个示例:

 $emailToRemove = "igor@gmx.de";
 $contents = file('database-email.txt'); //Read all lines
 $contents = array_filter($contents, function ($email) use ($emailToRemove) {
      return trim($email, " \n\r,") != $emailToRemove;
 }); // Filter out the matching email
 file_put_contents('database-email.txt', implode("\n", $contents)); // Write back

以下是一个流式传输的替代方案,适用于文件太大无法放入内存的情况:
$emailToRemove = "igor@gmx.de";
$fh = fopen('database-email.txt', "r"); //Current file
$fout = fopen('database-email.txt.new', "w"); //New temporary file
while (($line = fgets($fh)) !== null) {
      if (trim($line," \n\r,") != $emailToRemove) {
         fwrite($fout, $line, strlen($line)); //Write to new file if needed
      } 
}
fclose($fh);
fclose($fout);

unlink('database-email.txt');  //Delete old file 
rename('database-email.txt.new', 'database-email.txt'); //New file is old file

也有一种方法可以在原地完成,以最小化额外需要的磁盘空间,但这更加棘手。


我之前遇到过这个问题,如果涉及的文件大小达到100GB,那么这个问题就会变成一个真正的噩梦 :( - IncredibleHat
@IncredibleHat 如果是这样,你真的需要考虑使用更适合大数据存储的数据库。不过我会更新问题,提供一种流式传输文件的方法。 - apokryfos

3
您可以通过编程实现它,即遍历每一行,如果不是要删除的内容,则将其添加到数组中,然后写回文件中。如下所示:
 $DELETE = "igor@gmx.de";

 $data = file("database-email.txt");

 $out = array();

 foreach($data as $line) {
     if(trim($line) != $DELETE) {
         $out[] = $line;
     }
 }

 $fp = fopen("database-email.txt", "w+");
 flock($fp, LOCK_EX);
 foreach($out as $line) {
     fwrite($fp, $line);
 }
 flock($fp, LOCK_UN);
 fclose($fp); 

1
首先使用 fopenfget 读取文件,并创建一个数组来列出您想要删除的电子邮件地址,使用 in_array 检查值是否存在于数组中,然后在删除不需要的电子邮件地址后使用 fwrite 保存文件,并在读写操作后使用 fclose 关闭文件。
请查看以下代码:
$data = "";
$emailsToRemove = ["igor@gmx.de" , "janny@live.nl"];

//open to read
$f = fopen('databse-email.txt','r');
while ($line = fgets($f)) {
    $emailWithComma = $line . ",";

    //check if email marked to remove
    if(in_array($emailWithComma , $emailsToRemove))
        continue;

    $data = $data . $line;
}

fclose($f);


//open to write
$f = fopen('databse-email.txt','w');
fwrite($f, $data);
fclose($fh);

1

如果需要删除特殊字符并且删除空行,请尝试以下方法:

$file = "file_name.txt";
$search_for = "example_for_remove";
$file_data = file_get_contents($file);
$pattern = "/$search_for/mi";
$file_data_after_remove_word = preg_replace($pattern, '', $file_data);
$file_data_after_remove_blank_line = preg_replace("/(^[\r\n]*|[\r\n]+)[\s\t]*[\r\n]+/", "\n", $file_data_after_remove_word);
file_put_contents($file,$file_data_after_remove_blank_line);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接