2015-09-03 97 views
4

我試圖從大文件中刪除一行。 (> 20MB)。我知道要刪除的行的開頭文件中的位置。從大文件中刪除一行php

這是我目前有。

/** 
* 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); 
} 

但是,雖然上面的代碼確實從文件中刪除了行;因爲臨時文件比原始文件短。原始文件的尾端仍然存在並且翻倍。

例如: 原始文件是

  1. 一個
  2. b
  3. Ç
  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); 
} 
+0

可能的重複[如何從文本文件中使用PHP刪除一些行?](http://stackoverflow.com/questions/14250773/how-to-remove-some-line-from-text-file-using- php) – cmorrissey

+1

該文件具有> 200,000行,可能包含> 400,000。我感覺好像將整個文件加載到數組(內存)中效率相當低。這就是爲什麼我嘗試了上述方法,但遇到了這個問題。 – user4775085

回答

1

我覺得你非常接近解決方案。

我會堅持你從文件末尾去除$lengthRemoved的想法和建議的fclose(),其中規模大小截斷爲(大小= originalFilesize - lengthRemoved)前使用ftruncate($handle, $size);

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

+0

謝謝!那是我正在尋找的功能。 – user4775085

+0

很高興我能幫忙:) –

1

由於您的文件是非常大的您可能希望通過exec使用sed命令,如果你的PHP安裝將允許您使用該功能。

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

其中3表示所需的行號。