How to delete a line from the file with php?

后端 未结 9 1362
北荒
北荒 2020-11-27 19:36

I have a file named $dir and a string named $line, I know that this string is a complete line of that file but I don\'t know its line number and I

相关标签:
9条回答
  • 2020-11-27 20:17

    Convert text to array, remove first line and reconvert to text

    $line=explode("\r\n",$text);
    unset($line[0]);
    $text=implode("\r\n",$line);
    
    0 讨论(0)
  • 2020-11-27 20:20

    Read the lines one by one, and write all but the matching line to another file. Then replace the original file.

    0 讨论(0)
  • 2020-11-27 20:22

    I think the best way to work with files is to act them like strings:

    /**
     * Removes the first found line inside the given file.
     *
     * @param string $line The line content to be searched.
     * @param string $filePath Path of the file to be edited.
     * @param bool $removeOnlyFirstMatch Whether to remove only the first match or
     * the whole matches.
     * @return bool If any matches found (and removed) or not.
     *
     * @throw \RuntimeException If the file is empty.
     * @throw \RuntimeException When the file cannot be updated.
     */
    function removeLineFromFile(
        string $line,
        string $filePath,
        bool $removeOnlyFirstMatch = true
    ): bool {
        // You can wrap it inside a try-catch block
        $file = new \SplFileObject($filePath, "r");
    
        // Checks whether the file size is not zero
        $fileSize = $file->getSize();
        if ($fileSize !== 0) {
            // Read the whole file 
            $fileContent = $file->fread($fileSize);
        } else {
            // File is empty
            throw new \RuntimeException("File '$filePath' is empty");
        }
    
        // Free file resources
        $file = null;
    
        // Divide file content into its lines
        $fileLineByLine = explode(PHP_EOL, $fileContent);
    
        $found = false;
        foreach ($fileLineByLine as $lineNumber => $thisLine) {
            if ($thisLine === $line) {
                $found = true;
                unset($fileLineByLine[$lineNumber]);
    
                if ($removeOnlyFirstMatch) {
                    break;
                }
            }
        }
    
        // We don't need to update file either if the line not found
        if (!$found) {
            return false;
        }
    
        // Join lines together
        $newFileContent = implode(PHP_EOL, $fileLineByLine);
    
        // Finally, update the file
        $file = new \SplFileObject($filePath, "w");
        if ($file->fwrite($newFileContent) !== strlen($newFileContent)) {
            throw new \RuntimeException("Could not update the file '$filePath'");
        }
    
        return true;
    }
    

    Here is a brief description of what is being done: Get the whole file content, split the content into its lines (i.e. as an array), find the match(es) and remove them, join all lines together, and save the result back to the file (only if any changes happened).

    Let's now use it:

    // $dir is your filename, as you mentioned
    removeLineFromFile($line, $dir);
    

    Notes:

    • You can use fopen() family functions instead of SplFileObject, but I do recommend the object form, as it's exception-based, more robust and more efficient (in this case at least).

    • It's safe to unset() an element of an array being iterated using foreach (There's a comment here showing it can lead unexpected results, but it's totally wrong: As you can see in the example code, $value is copied (i.e. it's not a reference), and removing an array element does not affect it).

    • $line should not have new line characters like \n, otherwise, you may perform lots of redundant searches.

    • Don't use

      $fileLineByLine[$lineNumber] = "";
      // Or even
      $fileLineByLine[$lineNumber] = null;
      

      instead of

      unset($fileLineByLine[$key]);
      

      The reason is, the first case doesn't remove the line, it just clears the line (and an unwanted empty line will remain).

    Hope it helps.

    0 讨论(0)
提交回复
热议问题