Подтвердить что ты не робот

Наименее интенсивный способ чтения файла в PHP

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

Кроме того, длина сохраненных строк является переменной.

Вот код. Также файл 700kB не mB.

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;
}
4b9b3361

Ответ 1

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

$handle = fopen($filename, 'r');
if ($handle) {
    while (!feof($handle)) {
        echo fread($handle, 8192);
    }
    fclose($handle);
}

Ответ 2

ИЗМЕНИТЬ после обновления вопроса и комментарии к ответу fabjoa:

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

Пример 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;
}

Довольно сильно (если не дублировать):

Ответ 3

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

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

    // length is a large number or calculated from an initial file scan
    while (!feof($handle)) {
        $buffer = fgets($handle, $length);
        echo $buffer;
    }

Ответ 4

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

Ответ 5

Старый вопрос, но так как я не видел никого, кто бы упоминал об этом, 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;
}