从PHP中的文件中删除最后一行

从文件中删除最后一行是一个简单的过程,只需几行代码即可完成。

// 将文件读入数组
$lines = file('file.txt');
 
// 从数组中弹出最后一项 
array_pop($lines);
 
// 将数组连接回字符串
$file = join('', $lines);
 
// 将字符串写回到文件中 
$file_handle = fopen('file.txt', 'w');
fputs($file_handle, $file);
fclose($file_handle);

此脚本中方法的局限性在于,如果文件很大,则将整个文件传递到数组中将占用大量内存,从而有可能导致服务器崩溃。最好的方法不是执行此操作,而是从文件末尾开始直到找到第一个换行符为止。以下脚本将一次咬掉50个字符,直到找到换行符为止(而不是文件末尾的换行符)。在这一点上,循环退出,直到找到的换行符被写回到文件中为止。

// 文档名称
$filename = 'file.txt';
 
// 打开文件
$file_handle = fopen($filename, 'r');
 
// 设置循环变量
$linebreak  = false;
$file_start = false;
 
// 要查看的字节数
$bite = 50;
 
// 文件大小
$filesize = filesize($filename);
 
// 将指针放在文件末尾。
fseek($file_handle, 0, SEEK_END);
 
while ($linebreak === false && $file_start === false) {
    // 获取当前文件位置。
    $pos = ftell($file_handle);
 
    if ($pos < $bite) {
	// 如果位置小于一口,则转到文件的开头
        rewind($file_handle);
    } else { 
        // 将$bite个字符移回文件
        fseek($file_handle, -$bite, SEEK_CUR);
    }
 
    // 将文件的$bite个字符读入字符串。
    $string = fread($file_handle, $bite) or die ("Can't read from file " . $filename . ".");
 
    /* If we happen to have read to the end of the file then we need to ignore 
     * the last line as this will be a new line character.
     */
    if ($pos + $bite >= $filesize) {
        $string = substr_replace($string, '', -1);
    }
 
    // 由于我们将fred()前进到文件中,因此需要备份$bite字符。 
    if ($pos < $bite) {
	// 如果位置小于一口,则转到文件的开头
        rewind($file_handle);
    } else { 
        // 将$bite个字符移回文件
        fseek($file_handle, -$bite, SEEK_CUR);
    }
 
    // 我们读取的字符串中是否有换行符?
    if (is_integer($lb = strrpos($string, "\n"))) {
        // 将$linebreak设置为true,以便我们跳出循环
        $linebreak = true;
        // 文件中的最后一行在换行符之后
        $line_end = ftell($file_handle) + $lb + 1; 
    }
 
    if  (ftell($file_handle) == 0) {
       // 如果我们位于文件的开头,请跳出循环。 
       $file_start = true;
    }
}
 
if ($linebreak === true) {
    // 如果找到换行符,则将文件读入字符串以写入而无需最后一行。
    rewind($file_handle);
    $file_minus_lastline = fread($file_handle, $line_end);
 
    // 关闭档案
    fclose($file_handle);
 
    // 以写入模式打开文件并截断​​它。
    $file_handle = fopen($filename, 'w+');
    fputs($file_handle, $file_minus_lastline);
    fclose($file_handle);
} else {
    // 关闭档案, nothing else to do.
    fclose($file_handle);
}

该脚本使用fseek()和ftell()以小增量在文件中向后移动。我已经用从几千字节到超过100兆字节的一些文件大小进行了测试,并且可以非常快速地工作。比将文件转换为数组快得多。