Хорошо, я ищу самый быстрый способ прочитать все содержимое файла через php с файловой дорожкой на сервере, также эти файлы могут быть огромными. Поэтому очень важно, чтобы он выполнял ТОЧНУЮ ТОЛЬКО к нему как можно быстрее.
Читает ли это по очереди быстрее, чем чтение всего содержимого? Хотя, я помню, что читал об этом, что чтение всего содержимого может привести к ошибкам для огромных файлов. Это правда?
Если вы хотите загрузить полное содержимое файла в переменную PHP, самым простым (и, возможно, самым быстрым) способом будет file_get_contents
.
Но если вы работаете с большими файлами, загрузка всего файла в память может быть не такой хорошей идеей: вы, вероятно, закончите с ошибкой memory_limit
, так как PHP не позволит вашему скрипту использовать больше, чем (обычно) пара мегабайт памяти.
Таким образом, даже если это не самое быстрое решение, чтение строки по строке ( fopen
+ fgets
+ fclose
) и работа с этими линиями «на лету», без необходимости загрузки всего файла в память, может быть необходимо …
file_get_contents()
является наиболее оптимизированным способом чтения файлов на PHP, однако, поскольку вы читаете файлы в памяти, вы всегда ограничены объемом доступной памяти .
Вы можете выпустить ini_set('memory_limit', -1)
если у вас есть права, но вы все равно будете ограничены объемом памяти, доступным в вашей системе, что является общим для всех языков программирования.
Единственное решение – прочитать файл в кусках , для этого вы можете использовать file_get_contents()
с четвертым и пятым аргументами ( $offset
и $maxlen
– заданы в байтах ):
string file_get_contents(string $filename[, bool $use_include_path = false[, resource $context[, int $offset = -1[, int $maxlen = -1]]]])
Вот пример, когда я использую этот метод для работы с большими файлами загрузки:
public function Download($path, $speed = null) { if (is_file($path) === true) { set_time_limit(0); while (ob_get_level() > 0) { ob_end_clean(); } $size = sprintf('%u', filesize($path)); $speed = (is_int($speed) === true) ? $size : intval($speed) * 1024; header('Expires: 0'); header('Pragma: public'); header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); header('Content-Type: application/octet-stream'); header('Content-Length: ' . $size); header('Content-Disposition: attachment; filename="' . basename($path) . '"'); header('Content-Transfer-Encoding: binary'); for ($i = 0; $i <= $size; $i = $i + $speed) { ph()->HTTP->Flush(file_get_contents($path, false, null, $i, $speed)); ph()->HTTP->Sleep(1); } exit(); } return false; }
Другим вариантом является использование менее оптимизированных функций fopen()
, feof()
, fgets()
и fclose()
, особенно если вы хотите получить сразу все строки , вот еще один пример, который я представил в другом вопросе StackOverflow для импорта большого SQL запросов в базу данных :
function SplitSQL($file, $delimiter = ';') { set_time_limit(0); if (is_file($file) === true) { $file = fopen($file, 'r'); if (is_resource($file) === true) { $query = array(); while (feof($file) === false) { $query[] = fgets($file); if (preg_match('~' . preg_quote($delimiter, '~') . '\s*$~iS', end($query)) === 1) { $query = trim(implode('', $query)); if (mysql_query($query) === false) { echo '<h3>ERROR: ' . $query . '</h3>' . "\n"; } else { echo '<h3>SUCCESS: ' . $query . '</h3>' . "\n"; } while (ob_get_level() > 0) { ob_end_flush(); } flush(); } if (is_string($query) === true) { $query = array(); } } return fclose($file); } } return false; }
Какой метод вы используете, действительно будет зависеть от того, что вы пытаетесь сделать (как вы можете видеть с помощью функции импорта SQL и функции загрузки), но вам всегда придется читать данные в кусках .
$file_handle = fopen("myfile", "r"); while (!feof($file_handle)) { $line = fgets($file_handle); echo $line; } fclose($file_handle);
$file_handle
файл $file_handle
качестве ссылки на сам файл. Вы можете использовать file_get_contents
Пример:
$homepage = file_get_contents('http://www.example.com/'); echo $homepage;
Используйте fpassthru или readfile. Оба используют постоянную память с увеличением размера файла.
foreach (new SplFileObject($filepath) as $lineNumber => $lineContent) { echo $lineNumber."==>".$lineContent; //process your operations here }
Чтение всего файла за один раз происходит быстрее.
Но огромные файлы могут съесть всю вашу память и вызвать проблемы. Тогда ваша самая безопасная ставка – читать по строкам.
Если вы не беспокоитесь о размере памяти и файлах,
$lines = file($path);
$ lines – это массив файла.
Вы можете попробовать cURL ( http://php.net/manual/en/book.curl.php ).
Altho, вы можете проверить, у него есть свои ограничения
$ch = curl_init(); curl_setopt($ch, CURLOPT_URL, "http://example.com/"); curl_setopt ($ch, CURLOPT_RETURNTRANSFER, 1); $data = curl_exec ($ch); // Whole Page As String curl_close ($ch);