Наименее интенсивный способ чтения файла в PHP - PullRequest
12 голосов
/ 03 июля 2010

Я читаю файл, содержащий около 50 тыс. Строк, используя функцию file () в Php.Тем не менее, это дает ошибку нехватки памяти, так как содержимое файла хранится в памяти в виде массива.Есть ли другой способ?

Кроме того, длина хранимых строк является переменной.Также размер файла составляет 700 КБ, а не МБ.

private static function readScoreFile($scoreFile)
{
    $file = file($scoreFile);
    $relations = array();

    for($i = 1; $i < count($file); $i++)
    {
        $relation = explode("\t",trim($file[$i]));
        $relation = array(
                        'pwId_1' => $relation[0],
                        'pwId_2' => $relation[1],
                        'score' => $relation[2],
                        );
        if($relation['score'] > 0)
        {
            $relations[] = $relation;
        }
    }

    unset($file);
    return $relations;
}

Ответы [ 5 ]

13 голосов
/ 03 июля 2010

Используйте fopen, fread и fclose для последовательного чтения файла:

$handle = fopen($filename, 'r');
if ($handle) {
    while (!feof($handle)) {
        echo fread($handle, 8192);
    }
    fclose($handle);
}
9 голосов
/ 03 июля 2010

РЕДАКТИРОВАТЬ после обновления вопроса и комментарии к ответу fabjoa :

Определенно есть что-то подозрительное, если файл размером 700 Кбайт потребляет 140 МБ памяти с тем кодом, который вы дали (хотя вы можете установить соотношение unset $ в конце каждой итерации). Подумайте об использовании отладчика, чтобы пройти через него и посмотреть, что произойдет. Возможно, вы также захотите переписать код, чтобы использовать функции CSV SplFileObject ( или их процедурные родственники )

Пример SplFileObject :: setCsvControl

$file = new SplFileObject("data.csv");
$file->setFlags(SplFileObject::READ_CSV);
$file->setCsvControl('|');
foreach ($file as $row) {
    list ($fruit, $quantity) = $row;
    // Do something with values
}

Для подхода ООП для перебора файла попробуйте SplFileObject:

Пример SplFileObject :: fgets

$file = new SplFileObject("file.txt");
while (!$file->eof()) {
    echo $file->fgets();
}

SplFileObject :: следующий пример

// Read through file line by line
$file = new SplFileObject("misc.txt");
while (!$file->eof()) {
    echo $file->current();
    $file->next();
}

или даже

foreach(new SplFileObject("misc.txt") as $line) {
    echo $line;
}

В значительной степени связано (если не дублируется):

1 голос
/ 03 июля 2010

Если вы не знаете максимальную длину строки и вам неудобно использовать магическое число для максимальной длины строки, вам потребуется выполнить начальный просмотр файла и определить максимальную длину строки. *

Кроме этого вам должен помочь следующий код:

    // length is a large number or calculated from an initial file scan
    while (!feof($handle)) {
        $buffer = fgets($handle, $length);
        echo $buffer;
    }
0 голосов
/ 11 января 2019

Старый вопрос, но так как я не видел никого, кто бы упоминал об этом, PHP генераторы - отличный способ уменьшить потребление памяти.

Например:

function read($fileName)
{
    $fileHandler = fopen($fileName, 'rb');

    while(($line = fgets($fileHandler)) !== false) {
        yield rtrim($line, "\r\n");
    }

    fclose($fileHandler);
}

foreach(read(__DIR__ . '/filenameHere') as $line) {
    echo $line;
}
0 голосов
/ 03 июля 2010

выделяет больше памяти во время операции, может быть что-то вроде ini_set ('memory_limit', '16M') ;.Не забудьте вернуться к начальному выделению памяти после завершения операции

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...