For simple file reading, we usually use methods like file_get_contents() to get the contents of the file directly. A serious problem with this function, however, is that it loads the file into memory all at once, which means that it is limited by memory. Therefore, this should never be used when loading large files. Let’s first look at an example of loading this way.

// A normal file reads a 2.4GB SQL export file
$fileName= './2020-02-23.sql';

// file_get_contents
$fileInfo = file_get_contents($fileName);
// Fatal error: Allowed memory size of 134217728 bytes exhausted

// file
$fileInfo = file($fileName);
// Fatal error: Allowed memory size of 134217728 bytes exhausted

// fopen + fread
$fileHandle = fopen($fileName.'r');
$fileInfo = fread($fileHandle, filesize($fileName));
// Fatal error: Allowed memory size of 134217728 bytes exhausted
Copy the code

None of the above methods can load files of this size. Of course, you can modify the configuration in php.ini to make it work, but this is not recommended because memory resources are much more valuable than hard disk resources.

This large file can be read directly in the following ways:

// Readfile can only be output directly
echo readfile($fileName);

// fopen + fgetc
$fileHandle = fopen($fileName.'r');
// Outputs a single character until end-of-file
while(! feof($fileHandle)) {
    echo fgetc($fileHandle);
}
fclose($fileHandle);

// SplFileObject
$fileObject = new SplFileObject($fileName.'r');
while(!$fileObject->eof()){
    echo $fileObject->fgetc();
}
Copy the code

The first readfile(), which prints the file after reading it, cannot do anything else, and is suitable for displaying the contents of large files directly.

The second fopen() with fgetc() or fgets() is standard for reading such large files. Fopen () gets a file handle, fgetc() reads by character, and fgets() reads by line. Files like this mysqldump can be very large in a single line, so we can only read them by character.

The third is the object oriented fopen() operation provided by the SPL extension library. It is suggested that if there is a requirement to read large files in the new development, it is best to use this form of writing method. After all, THE SPL function library has been the standard function library of PHP, and the object oriented operation form is also more mainstream.

One thing to note about all the above three reading methods is that we should not save large files to variables after reading them. We should directly print them for display, put them into the library, or write them to other files. Since reading directly into a variable is the same as reading directly into memory, it is better to modify the php.ini configuration and read directly into memory using the top method. Still, the memory is reserved for where it is really needed, and it is best to perform IO operations on hard disks for such large files.

Test code: github.com/zhangyue050…

Reference document: “PHP7 Programming Combat”