php 这是获取和删除文件第一行的最有效方法吗?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2404707/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Is this the most efficient way to get and remove first line in file?
提问by Marco Demaio
I have a script which, each time is called, gets the first line of a file. Each line is known to be exactly of the same length (32 alphanumeric chars) and terminates with "\r\n". After getting the first line, the script removes it.
我有一个脚本,每次调用它都会获取文件的第一行。已知每一行的长度完全相同(32 个字母数字字符)并以“\r\n”结尾。获取第一行后,脚本将其删除。
This is done in this way:
这是通过这种方式完成的:
$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
Obviously it works, but I was wondering whether there is a smarter (or more efficient) way to do this?
显然它有效,但我想知道是否有更聪明(或更有效)的方法来做到这一点?
In my simple solution I basically read and rewrite the entire file just to take and remove the first line.
在我的简单解决方案中,我基本上读取和重写整个文件只是为了取出和删除第一行。
采纳答案by Byron Whitlock
There is no more efficient way to do this other than rewriting the file.
除了重写文件之外,没有更有效的方法可以做到这一点。
回答by Daniel
I came up with this idea yesterday:
我昨天想出了这个主意:
function read_and_delete_first_line($filename) {
$file = file($filename);
$output = $file[0];
unset($file[0]);
file_put_contents($filename, $file);
return $output;
}
回答by Edakos
No need to create a second temporary file, nor put the whole file in memory:
无需创建第二个临时文件,也无需将整个文件放入内存中:
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);
}
回答by Marcos Fernandez Ramos
This will shift the first line of a file, you dont need to load the entire file in memory like you do using the 'file' function. Maybe for small files is a bit more slow than with 'file' (maybe but i bet is not) but is able to manage largest files without problems.
这将移动文件的第一行,您不需要像使用“文件”函数那样将整个文件加载到内存中。也许对于小文件来说比'文件'慢一点(也许但我敢打赌不是)但是能够毫无问题地管理最大的文件。
$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);
}
回答by ghostdog74
you can iterate the file , instead of putting them all in memory
您可以迭代文件,而不是将它们全部放在内存中
$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);
回答by Frank Farmer
I wouldn't usually recommend opening up a shell for this sort of thing, but if you're doing this infrequently on really large files, there's probably something to be said for:
我通常不建议为这种事情打开一个 shell,但如果你很少在非常大的文件上这样做,那么可能有一些事情要说:
$lines = `wc -l myfile` - 1;
`tail -n $lines myfile > newfile`;
It's simple, and it doesn't involve reading the whole file into memory.
这很简单,它不涉及将整个文件读入内存。
I wouldn't recommend this for small files, or extremely frequent use though. The overhead's too high.
我不会推荐这个用于小文件,或者非常频繁地使用。开销太高了。
回答by goat
You could store positional info into the file itself. For example, the first 8 bytes of the file could store an integer. This integer is the byte offset of the first real line in the file.
您可以将位置信息存储到文件本身中。例如,文件的前 8 个字节可以存储一个整数。这个整数是文件中第一个实行的字节偏移量。
So, you never delete lines anymore. Instead, deleting a line means altering the start position. fseek() to it and then read lines as normal.
所以,你永远不会再删除行了。相反,删除一行意味着改变起始位置。fseek() 到它,然后正常读取行。
The file will grow big eventually. You could periodically clean up the orphaned lines to reduce the file size.
文件最终会变大。您可以定期清理孤立的行以减小文件大小。
But seriously, just use a database and don't do stuff like this.
但说真的,只要使用数据库,不要做这样的事情。
回答by Tatu Ulmanen
Here's one way:
这是一种方法:
$contents = file($file, FILE_IGNORE_NEW_LINES);
$first_line = array_shift($contents);
file_put_contents($file, implode("\r\n", $contents));
There's countless other ways to do that also, but all the methods would involve separating the first line somehow and saving the rest. You cannot avoid rewriting the whole file. An alternative take:
还有无数其他方法可以做到这一点,但所有方法都涉及以某种方式分离第一行并保存其余部分。您无法避免重写整个文件。另一种选择:
list($first_line, $contents) = explode("\r\n", file_get_contents($file), 2);
file_put_contents($file, implode("\r\n", $contents));
回答by Michael D. Irizarry
You could use file() method.
您可以使用 file() 方法。
Gets the first line
获取第一行
$content = file('myfile.txt');
echo $content[0];
回答by Kushlendr Pal Ahirwar
I think this is best for any file size
我认为这最适合任何文件大小
$myfile = fopen("yourfile.txt", "r") or die("Unable to open file!");
$ch=1;
while(!feof($myfile)) {
$dataline= fgets($myfile) . "<br>";
if($ch == 2){
echo str_replace(' ', ' ', $dataline)."\n";
}
$ch = 2;
}
fclose($myfile);

