这是获取和删除文件中第一行的最有效方法吗?

Mar*_*aio 15 php file

我有一个脚本,每次调用时,都会得到一个文件的第一行.已知每条线的长度完全相同(32个字母数字字符),并以"\ r \n"结尾.获取第一行后,脚本将其删除.

这是通过这种方式完成的:

$contents = file_get_contents($file));
$first_line = substr($contents, 0, 32);
file_put_contents($file, substr($contents, 32 + 2)); //+2 because we remove also the \r\n
Run Code Online (Sandbox Code Playgroud)

显然它有效,但我想知道是否有更智能(或更有效)的方法来做到这一点?

在我的简单解决方案中,我基本上读取并重写整个文件只是为了取下并删除第一行.

小智 22

我昨天提出了这个想法:

function read_and_delete_first_line($filename) {
  $file = file($filename);
  $output = $file[0];
  unset($file[0]);
  file_put_contents($filename, $file);
  return $output;
}
Run Code Online (Sandbox Code Playgroud)


Byr*_*ock 14

除了重写文件之外,没有更有效的方法可以做到这一点.


Eda*_*kos 14

无需创建第二个临时文件,也不需要将整个文件放在内存中:

if ($handle = fopen("file", "c+")) {             // open the file in reading and editing mode
    if (flock($handle, LOCK_EX)) {               // lock the file, so no one can read or edit this file 
        while (($line = fgets($handle, 4096)) !== FALSE) { 
            if (!isset($write_position)) {        // move the line to previous position, except the first line
                $write_position = 0;
            } else {
                $read_position = ftell($handle); // get actual line
                fseek($handle, $write_position); // move to previous position
                fputs($handle, $line);           // put actual line in previous position
                fseek($handle, $read_position);  // return to actual position
                $write_position += strlen($line);    // set write position to the next loop
            }
        }
        fflush($handle);                         // write any pending change to file
        ftruncate($handle, $write_position);     // drop the repeated last line
        flock($handle, LOCK_UN);                 // unlock the file
    }
    fclose($handle);
}
Run Code Online (Sandbox Code Playgroud)

  • 嗯...这次精神编译不起作用......固定. (2认同)

Mar*_*mos 6

这将移动文件的第一行,您不需要像使用"文件"功能一样将整个文件加载到内存中.也许对于小文件来说比使用'file'要慢一点(也许我打赌不是)但是能够毫无问题地管理最大的文件.

$firstline = false;
if($handle = fopen($logFile,'c+')){
    if(!flock($handle,LOCK_EX)){fclose($handle);}
    $offset = 0;
    $len = filesize($logFile);
    while(($line = fgets($handle,4096)) !== false){
        if(!$firstline){$firstline = $line;$offset = strlen($firstline);continue;}
        $pos = ftell($handle);
        fseek($handle,$pos-strlen($line)-$offset);
        fputs($handle,$line);
        fseek($handle,$pos);
    }
    fflush($handle);
    ftruncate($handle,($len-$offset));
    flock($handle,LOCK_UN);
    fclose($handle);
}
Run Code Online (Sandbox Code Playgroud)


gho*_*g74 5

您可以迭代文件,而不是将它们全部放在内存中

$handle = fopen("file", "r");
$first = fgets($handle,2048); #get first line.
$outfile="temp";
$o = fopen($outfile,"w");
while (!feof($handle)) {
    $buffer = fgets($handle,2048);
    fwrite($o,$buffer);
}
fclose($handle);
fclose($o);
rename($outfile,$file);
Run Code Online (Sandbox Code Playgroud)