题
PHP
中读取一个非常适中的文件时, fopen
失败了。 一个6兆字节的文件
使它窒息,但 100k
周围的小文件就好了。我已经读过有时需要使用 -D_FILE_OFFSET_BITS = 64
标志重新编译 PHP
,以便读取超过20场演出的文件或者荒谬的东西,但不应该6 meg文件没有问题?最终我们想要读取大约100兆的文件,并且能够打开它们然后逐行读取它们将很好,因为我可以使用较小的文件。
在 PHP
中读取和操作非常大的文件的技巧/解决方案是什么?
更新:这是一个在我的6 meg文件上失败的简单代码块的示例 - PHP似乎没有抛出错误,它只返回false。也许我正在做一些非常愚蠢的事情?
$rawfile = "mediumfile.csv";
if($file = fopen($rawfile, "r")){
fclose($file);
} else {
echo "fail!";
}
另一个更新:感谢所有人的帮助,它确实是令人难以置信的愚蠢 - 权限问题。当较大的文件没有时,我的小文件莫名其妙地具有读权限。卫生署!
解决方案
你确定它的 fopen
失败而不是脚本的超时设置吗?默认值通常约为30秒左右,如果您的文件花费的时间超过了读取的时间,则可能会使文件绊倒。
要考虑的另一件事可能是脚本的内存限制 - 将文件读入数组可能会超过此值,因此请检查错误日志中的内存警告。
如果以上都不是您的问题,您可以考虑使用 fgets
逐行读取文件,随时处理。
$handle = fopen("/tmp/uploadfile.txt", "r") or die("Couldn't get handle");
if ($handle) {
while (!feof($handle)) {
$buffer = fgets($handle, 4096);
// Process buffer here..
}
fclose($handle);
}
修改强>
PHP似乎没有抛出错误,它只返回false。
$ rawfile
的路径相对于脚本运行的位置是否正确?也许尝试在这里为文件名设置一个绝对路径。
其他提示
使用1.3GB文件和9.5GB文件进行了2次测试。
1.3 GB
使用 fopen()
此过程使用15555毫秒进行计算。
它在系统调用中花费了169毫秒。
使用 file()
此过程使用6983 ms进行计算。
它在系统调用中花了4469毫秒。
9.5 GB
使用 fopen()
此过程使用113559毫秒进行计算。
它在系统调用中花了2532毫秒。
使用 file()
此过程使用8221 ms进行计算。
它在系统调用中花费了7998毫秒。
似乎 file()
更快。
如果您只想输出文件,可以尝试使用readfile函数。
如果不是这种情况 - 也许您应该考虑应用程序的设计,为什么要在Web请求上打开如此大的文件?
我使用fopen打开视频文件进行流式传输,使用php脚本作为视频流服务器,我对大小超过50/60 MB的文件没有任何问题。
• fgets()
函数很好,直到文本文件传递20 MB,并且解析速度大大降低。
• file_ get_contents()
函数提供了良好的结果,直到40 MB并且可接受的结果直到100 MB,但 file_get_contents()
将整个文件加载到内存中 ,所以它不是scalabile。
• file()
函数对于大文本文件是灾难性的,因为此函数创建一个包含每行文本的数组,因此该数组存储在内存中,使用的内存更大。
实际上,我只能设置一个200 MB的文件来解析设置为2 GB的 memory_limit
,这对于我打算解析的1+ GB文件是不合适的。
当你必须解析大于1 GB的文件并且解析时间超过15秒并且你想避免将整个文件加载到内存中时,你必须找到另一种方法。
我的解决方案是以任意小块解析数据。代码是:
$filesize = get_file_size($file);
$fp = @fopen($file, "r");
$chunk_size = (1<<24); // 16MB arbitrary
$position = 0;
// if handle $fp to file was created, go ahead
if ($fp) {
while(!feof($fp)){
// move pointer to $position in file
fseek($fp, $position);
// take a slice of $chunk_size bytes
$chunk = fread($fp,$chunk_size);
// searching the end of last full text line
$last_lf_pos = strrpos($chunk, "\n");
// $buffer will contain full lines of text
// starting from $position to $last_lf_pos
$buffer = mb_substr($chunk,0,$last_lf_pos);
////////////////////////////////////////////////////
//// ... DO SOMETHING WITH THIS BUFFER HERE ... ////
////////////////////////////////////////////////////
// Move $position
$position += $last_lf_pos;
// if remaining is less than $chunk_size, make $chunk_size equal remaining
if(($position+$chunk_size) > $filesize) $chunk_size = $filesize-$position;
$buffer = NULL;
}
fclose($fp);
}
使用的内存只是 $ chunk_size
,速度略小于 file_ get_contents()
获得的速度。我认为PHP Group应该使用我的方法来优化它的解析功能。
*)在此处找到 get_file_size()
函数。
如果问题是由达到内存限制引起的,您可以尝试将其设置为更高的值(这可能有效或无效,具体取决于php的配置)。
这将内存限制设置为12 Mb
ini\_set("memory_limit","12M");
对我来说, fopen()
的速度非常慢,文件超过1mb, file()
要快得多。
只是尝试一次读取100行并创建批量插入, fopen()
需要37秒, file()
需要4秒。必须是内置于 file()
string-&gt; array
步骤
我会尝试所有文件处理选项,看看哪种方法最适合您的应用程序。
您是否尝试过文件()?
http://is2.php.net/manual/en/function .file.php
或者file_get_contents()
http://is2.php.net/manual /en/function.file-get-contents.php