3分钟短文|大神救我!18G的大文件 PHP咋按行读取?
引言
想逐行读取文件,完全避免把这个文件加载到内存中。如果文件太大(比如 18G),无法在内存中打开,还是要硬来的话,会抛出异常。
大小的编程语言都提供了文件的按行读写,PHP 怎会没有!
正确方法
是不能够使用 file_get_contents 函数,一股脑把所有文件内容扔到内存的。应该使用 fgets 函数逐行读取:
$handle = fopen("inputfile.txt", "r"); if ($handle) {while (($line = fgets($handle)) !== false) { // process the line read. } fclose($handle); } else { // error opening the file. }
首先打开文件句柄,然后逐行使用 fgets 读取,处理完毕后使用 fclose 显式关闭。
当然,你也可以不必使用 false 判断,转而使用 feof 检测是否到文件末尾即可:
if ($file = fopen("file.txt", "r")) {while(!feof($file)) { $line = fgets($file); # do same stuff with the $line }fclose($file);}
所谓“条条大道通罗马”,实现功能的方法不止一种。我们更推荐的是下面的这种写法。使用 PHP 5.1 之后提供的 SplFileObject 对象处理文件。
那么就可以这样写:
$file = new SplFileObject("file.txt");// Loop until we reach the end of the file. while (!$file->eof()) { // Echo one line from the file. echo $file->fgets(); } // Unset the file to call __destruct(), closing the file handle. $file = null;
这个对象提供了为数众多的方法用于文件操作:
比起我们常用的一些文件操作函数:
fgetss() - 从文件指针中读取一行并过滤掉 HTML 标记fread() - 读取文件(可安全用于二进制文件)fgetc() - 从文件指针中读取字符stream_get_line() - 从资源流里读取一行直到给定的定界符fopen() - 打开文件或者 URLpopen() - 打开进程文件指针fsockopen() - 打开一个网络连接或者一个Unix套接字连接stream_set_timeout() - Set timeout period on a streamSplFileObject 对象封装的更为灵活,如果嵌入到程序内使用,可以组装为十分强大的文件操作类。比一个个的操作函数,有更强的可扩展性。
写在最后
通过一个大文件的按行读取,我们引出了 SplFileObject 这个文件操作对象,希望大家仔细地学习一下,可以大大提升功力。
Happy coding :_)
我是 @程序员小助手 ,持续分享编程知识,欢迎关注。