Removing a line from the middle of a large php file

I am trying to remove a line from the middle of a large file. (> 20 MB). I know the position in the file of the beginning of the line that needs to be deleted.

Here is what I have now.

/**
 * Removes a line at a position from the file
 * @param  [int] $position  The position at the start of the line to be removed
 */
public function removeLineAt($position)
{
    $fp = fopen($this->filepath, "rw+");
    fseek($fp, $position);

    $nextLinePosition = $this->getNextLine($position, $fp);
    $lengthRemoved = $position - $nextLinePosition;
    $fpTemp = fopen('php://temp', "rw+");

    // Copy the bottom half (starting at line below the line to be removed)
    stream_copy_to_stream($fp, $fpTemp, -1, $nextLinePosition);

    // Seek to the start of the line to be removed
    fseek($fp, $position);
    rewind($fpTemp);

    // Copy the bottom half over the line to be removed
    stream_copy_to_stream($fpTemp, $fp);        

    fclose($fpTemp);
    fclose($fp);
}

However, although the code above does remove the line from the file; because the temporary file is shorter than the original file. The tail of the source file still exists and doubles.

For example: The source file was

  • a
  • b
  • from
  • d
  • e

The file after deleting the line may look like

  • a
  • b
  • d
  • e
  • e

I thought of somehow trimming the end of the main file using the $ lengthRemoved number, but I can't think of an easy way to do this.

Any suggestions?

  • . > 200 000 , a > 300 000. , () . , .

, , , ! .

/**
 * Removes a line at a position from the file
 * @param  [int] $position  The position at the start of the line to be removed
 */
public function removeLineAt($position)
{
    $fp = fopen($this->filepath, "rw+");
    fseek($fp, $position);

    $nextLinePosition = $this->getNextLine($position, $fp);
    $lengthRemoved = $position - $nextLinePosition;
    $fpTemp = fopen('php://temp', "rw+");

    // Copy the bottom half (starting at line below the line to be removed)
    stream_copy_to_stream($fp, $fpTemp, -1, $nextLinePosition);

    // Remove the difference
    $newFileSize = ($this->totalBytesInFile($fp) + $lengthRemoved);
    ftruncate($fp, $newFileSize);

    // Seek to the start of the line to be removed
    fseek($fp, $position);
    rewind($fpTemp);

    // Copy the bottom half over the line to be removed
    stream_copy_to_stream($fpTemp, $fp);        

    fclose($fpTemp);
    fclose($fp);
}
+4
2

, .

$lengthRemoved ftruncate($handle, $size); fclose(), - , (size = originalFilesize - lengthRemoved).

http://www.php.net/manual/en/function.ftruncate.php

+1

, sed exec, php .

exec("sed '3d' fileName.txt");

3 .

+1

Source: https://habr.com/ru/post/1605793/


All Articles