Самый быстрый способ прочитать содержимое файла - PullRequest
28 голосов
/ 01 мая 2010

Хорошо, я ищу самый быстрый способ прочитать все содержимое файла через php с помощью filepath на сервере, также эти файлы могут быть огромными. Поэтому очень важно, чтобы он выполнял ТОЛЬКО ЧТЕНИЕ как можно быстрее.

Чтение построчно быстрее, чем чтение всего содержимого? Хотя я помню, что читал об этом, что чтение всего содержимого может привести к ошибкам для огромных файлов. Это правда?

Ответы [ 9 ]

35 голосов
/ 01 мая 2010

Если вы хотите загрузить полное содержимое файла в переменную PHP, самый простой способ (и, возможно, самый быстрый) будет file_get_contents.

Но, если вы работаете с большими файлами, загрузка всего файла в память может быть не очень хорошей идеей: вы, вероятно, в итоге получите memory_limit ошибка, так как PHP не позволит вашему сценарию использовать более (обычно) пару мегабайт памяти.


Таким образом, даже если это не самое быстрое решение, читайте файл построчно (fopen + fgets + fclose) , и работа с этими строками на лету, без загрузки всего файла в память, может оказаться необходимой ...

15 голосов
/ 01 мая 2010

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 и функции загрузки), но вам всегда придется читать данные кусками .

8 голосов
/ 01 мая 2010
$file_handle = fopen("myfile", "r");
while (!feof($file_handle)) {
   $line = fgets($file_handle);
   echo $line;
}
fclose($file_handle);
  1. Открыть файл и сохранить в $file_handle как ссылку на сам файл.
  2. Проверьте, находитесь ли вы уже в конце файла.
  3. Продолжайте читать файл до конца, печатая каждую строку по мере ее чтения.
  4. Закройте файл.
5 голосов
/ 01 мая 2010

Вы можете использовать file_get_contents

Пример:

$homepage = file_get_contents('http://www.example.com/');
echo $homepage;
2 голосов
/ 21 мая 2011

Используйте fpassthru или readfile. Оба используют постоянную память с увеличением размера файла.

http://raditha.com/wiki/Readfile_vs_include

1 голос
/ 27 октября 2014
foreach (new SplFileObject($filepath) as $lineNumber => $lineContent) {

    echo $lineNumber."==>".$lineContent;  
    //process your operations here
}
0 голосов
/ 29 июня 2013

Вы могли бы попробовать cURL (http://php.net/manual/en/book.curl.php).

Хотя вы можете захотеть проверить, у него тоже есть свои ограничения

$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);
0 голосов
/ 10 апреля 2012

Если вас не беспокоит память и размер файла,

$lines = file($path);

$ строк - это массив файла.

0 голосов
/ 01 мая 2010

Чтение всего файла за один раз происходит быстрее.

Но огромные файлы могут съесть всю вашу память и вызвать проблемы. Тогда вам лучше всего читать построчно.

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