什么';搜索文件内容并用PHP更改内容的最佳(最有效)方法是什么?
我有一个用PHP读取的文件。我想寻找一些以空格开头的行,然后是我正在寻找的一些关键词(例如,“project_name:”),然后更改该行的其他部分什么';搜索文件内容并用PHP更改内容的最佳(最有效)方法是什么?,php,file,io,Php,File,Io,我有一个用PHP读取的文件。我想寻找一些以空格开头的行,然后是我正在寻找的一些关键词(例如,“project_name:”),然后更改该行的其他部分 目前,我处理这个问题的方法是将整个文件读入一个字符串变量,操纵该字符串,然后将整个内容写回文件,完全替换整个文件(通过fopen(filepath,“wb”)和fwrite()),但这感觉效率低下。有更好的方法吗?更新:完成函数后,我有时间对其进行基准测试。我使用了一个1GB大文件进行测试,但结果不令人满意:| 是的,内存峰值分配明显更小: 标准
目前,我处理这个问题的方法是将整个文件读入一个字符串变量,操纵该字符串,然后将整个内容写回文件,完全替换整个文件(通过
fopen(filepath,“wb”)
和fwrite()
),但这感觉效率低下。有更好的方法吗?更新:完成函数后,我有时间对其进行基准测试。我使用了一个1GB
大文件进行测试,但结果不令人满意:|
是的,内存峰值分配明显更小:
- 标准溶液:1,86 GB
- 自定义解决方案:653 KB(4096字节缓冲区大小)
ini_set('memory_limit', -1);
file_put_contents(
'test.txt',
str_replace('the', 'teh', file_get_contents('test.txt'))
);
上面的脚本耗时约16秒,自定义解决方案耗时约13秒
简历:custome解决方案在处理大文件时速度稍快,占用的内存也少得多(!!!)
另外,如果您希望在web服务器环境中运行此功能,那么定制解决方案会更好,因为许多并发脚本可能会消耗整个系统的可用内存
原始答案: 记住的唯一一件事是,按照文件系统块的大小分块读取文件,然后将内容或修改的内容写回临时文件。完成处理后,使用
rename()
覆盖原始文件
这将减少内存峰值,如果文件确实很大,则速度应该会明显加快
注意:在linux系统上,可以使用以下方法获得文件系统块大小:
sudo dumpe2fs /dev/yourdev | grep 'Block size'
我得到了4096
功能如下:
function freplace($search, $replace, $filename, $buffersize = 4096) {
$fd1 = fopen($filename, 'r');
if(!is_resource($fd1)) {
die('error opening file');
}
// the tempfile can be anywhere but on the same partition as the original
$tmpfile = tempnam('.', uniqid());
$fd2 = fopen($tmpfile, 'w+');
// we store len(search) -1 chars from the end of the buffer on each loop
// this is the maximum chars of the search string that can be on the
// border between two buffers
$tmp = '';
while(!feof($fd1)) {
$buffer = fread($fd1, $buffersize);
// prepend the rest from last one
$buffer = $tmp . $buffer;
// replace
$buffer = str_replace($search, $replace, $buffer);
// store len(search) - 1 chars from the end of the buffer
$tmp = substr($buffer, -1 * (strlen($search)) + 1);
// write processed buffer (minus rest)
fwrite($fd2, $buffer, strlen($buffer) - strlen($tmp));
};
if(!empty($tmp)) {
fwrite($fd2, $tmp);
}
fclose($fd1);
fclose($fd2);
rename($tmpfile, $filename);
}
可以这样称呼:
freplace('foo', 'bar', 'test.txt');
“最好”是主观的。从“接近”的理由来看,“我们期望答案是由事实、参考文献或特定的专门知识所支持的,但是这个问题可能会引起辩论、争论、轮询或扩展讨论。”你会考虑通过选择一个特定的方法来解释你的问题,并解释它如何不符合你的需要吗?这将允许is提供具体而非主观的答案。@GeorgeCummins您的评论在这里不适用。这是一个典型的编程question@Baba你确定你的尝试比那次快吗?请注意,简单的
rename()
非常快。将准备一些基准测试:)还请注意,在大多数应用程序中,不知道应该在哪里替换字符串scenarios@hek2mgl我想你应该做你的测试。。。。你的功能有很多问题。。这使速度慢了10倍。。。而且expensive@Baba我仍然不明白这是怎么一个重复,你的答案如何适合这里。您有一个位置,文本应该被替换为函数的参数。请注意,此处不知道位置。它是搜索和替换,而不是注入。你能告诉我我的答案有哪些错误吗?我想对这两种解决方案进行基准测试(也许会改进),但我无法对它们进行比较,因为它们并不相同。我知道你是一个聪明的人,也许我遗漏了一些东西,如果搜索字符串跨读缓冲区会发生什么?谢谢你的评论。我已经更新了帖子。是的,要想获得这种防弹效果,需要更多的关注。@hek2mgl这样做是否有好处,而不是用“x+”开头,然后结合这些步骤?是的。好处是降低了内存峰值。您只需要~$buffersize内存,而不是文件大小。不过,我会在有时间的时候更新帖子。也许在晚上。将准备一个处理Jon评论的版本。。差不多准备好了:)@Jon已经更新了帖子来处理你的评论。谢谢你。当然,这不适用于正则表达式