从大文件php的中间删除一行

use*_*085 5 php file

我试图从大文件的中间删除一行.(> 20MB).我知道要删除的行开头的文件中的位置.

这是我现在拥有的.

/**
 * 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);
}
Run Code Online (Sandbox Code Playgroud)

但是,虽然上面的代码确实从文件中删除了该行; 因为临时文件比原始文件短.原始文件的尾端仍然存在并且加倍.

例如:原始文件是

  1. 一个
  2. b
  3. C
  4. d
  5. Ë

删除行后的文件可能看起来像

  1. 一个
  2. b
  3. d
  4. Ë
  5. Ë

我已经想过用$ lengthRemoved量以某种方式修剪主文件的结尾但是我想不出一个简单的方法来做到这一点.

有什么建议?

  • 注意:该文件有> 200,000行,有时> 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);
}
Run Code Online (Sandbox Code Playgroud)

Jen*_*och 1

我认为你已经非常接近解决方案了。

我会坚持您$lengthRemoved从文件末尾删除 的想法,并建议ftruncate($handle, $size);在 之前使用fclose(),其中 size 是要截断的大小(size = originalFilesize - lengthRemoved)。

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