Как читать файл по строкам в PHP, без полной загрузки его в память?
Мой файл слишком велик для открытия в памяти, поэтому я всегда получаю ошибки выхлопа памяти.
Размер файла – 1 ГБ.
Вы можете использовать функцию fgets()
для чтения файла по строкам:
$handle = fopen("inputfile.txt", "r"); if ($handle) { while (($line = fgets($handle)) !== false) { // process the line read. } fclose($handle); } else { // error opening the file. }
if ($file = fopen("file.txt", "r")) { while(!feof($file)) { $line = fgets($file); # do same stuff with the $line } fclose($file); }
Вы можете использовать объектно-ориентированный класс интерфейса для файла – SplFileObject http://php.net/manual/en/splfileobject.fgets.php (PHP 5> = 5.1.0)
<?php $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;
Используйте методы буферизации для чтения файла.
$filename = "test.txt"; $source_file = fopen( $filename, "r" ) or die("Couldn't open $filename"); while (!feof($source_file)) { $buffer = fread($source_file, 4096); // use a buffer of 4KB $buffer = str_replace($old,$new,$buffer); /// }
Существует функция file()
которая возвращает массив строк, содержащихся в файле.
foreach(file('myfile.txt') as $line) { echo $line. "\n"; }
foreach (new SplFileObject(__FILE__) as $line) { echo $line; }
Если вы открываете большой файл, вы, вероятно, захотите использовать генераторы вместе с fgets (), чтобы избежать загрузки всего файла в память:
/** * @return Generator */ $fileData = function() { $file = fopen(__DIR__ . '/file.txt', 'r'); if (!$file) die('file does not exist or cannot be opened'); while (($line = fgets($file)) !== false) { yield $line; } fclose($file); };
Используйте его так:
foreach ($fileData() as $line) { // $line contains current line }
Таким образом, вы можете обрабатывать отдельные строки файлов внутри foreach ().
Примечание: Генераторы требуют> = PHP 5.5
Будьте осторожны с «while (! Feof … fgets ()», fgets может получить ошибку (returnfing false) и цикл навсегда, не дойдя до конца файла. Codaddict был ближе всего к правильному, но когда ваш 'while fgets' концы цикла, проверьте феоф, если это не так, значит, у вас была ошибка.
Одно из популярных решений этого вопроса будет иметь проблемы с новым характером линии. С простым str_replace
его можно легко str_replace
.
$handle = fopen("some_file.txt", "r"); if ($handle) { while (($line = fgets($handle)) !== false) { $line = str_replace("\n", "", $line); } fclose($handle); }
Это то, как я справляюсь с очень большим файлом (тестируется до 100G). И это быстрее, чем fgets ()
$block =1024*1024;//1MB or counld be any higher than HDD block_size*2 if( $fh = fopen("file.txt", "r") ){ $left=''; while (!feof($fh)) {// read the file $temp = fread($fh, $block); $fgetslines = explode("\n",$temp); $lines[0]=$left.$lines[0]; if(!feof($fh) )$left = array_pop($lines); foreach($lines as $k => $line){ //do smth with $line } } } fclose($fh);
Функция чтения с возвратом массива
function read_file($filename = ''){ $buffer = array(); $source_file = fopen( $filename, "r" ) or die("Couldn't open $filename"); while (!feof($source_file)) { $buffer[] = fread($source_file, 4096); // use a buffer of 4KB } return $buffer; }