Управляйте строкой, которая является 30 миллионами символов в длину

Если значение текста семантически сильно , используйте strong элемент. В противном случае используйте семантический именованный класс (тот, который ясно показывает значение элемента, не смешивайте представление и данные путем вызова его bold и т.д.), и сошлитесь на него в CSS.

CSS

.important-message {
   font-weight: bold;
}

HTML

I'm important!

Некоторые люди все еще используют b элемент как представляемый рычаг, но он не был удержан от использования , хотя большинство людей одобряет strong элемент в наше время. Просто удостоверьтесь, что они используются правильно.

11
задан JD Isaacks 1 May 2013 в 20:36
поделиться

6 ответов

PHP задыхается из-за нехватки памяти. Вместо того, чтобы указывать curl для заполнения переменной PHP содержимым файла, используйте параметр

CURLOPT_FILE

для сохранения файла на диск.

//pseudo, untested code to give you the idea

$fp = fopen('path/to/save/file', 'w');
curl_setopt($ch, CURLOPT_FILE, $fp);
curl_exec ($ch);
curl_close ($ch);
fclose($fp);

Затем, когда файл будет сохранен, вместо использования файла ] или file_get_contents (которые загружают весь файл в память, снова убивая PHP), используйте fopen и fgets для чтения файла по одной строке за раз. .

18
ответ дан 3 December 2019 в 00:38
поделиться

Как сказано в других ответах:

  • у вас не может быть всего этого в памяти
  • , решением было бы использовать CURLOPT_FILE

Но вы, возможно, не захотите действительно создать файл, который вы могли бы захотеть работать с данными в памяти ... Используя его, как только он «прибудет».

Одним из возможных решений может быть определение вашей собственной оболочки потока и использование этого вместо реального файла , с CURLOPT_FILE

Прежде всего, см .:


А теперь давайте рассмотрим пример.

Сначала , давайте создадим наш класс-оболочку потока:

class MyStream {
    protected $buffer;

    function stream_open($path, $mode, $options, &$opened_path) {
        // Has to be declared, it seems...
        return true;
    }

    public function stream_write($data) {
        // Extract the lines ; on y tests, data was 8192 bytes long ; never more
        $lines = explode("\n", $data);

        // The buffer contains the end of the last line from previous time
        // => Is goes at the beginning of the first line we are getting this time
        $lines[0] = $this->buffer . $lines[0];

        // And the last line os only partial
        // => save it for next time, and remove it from the list this time
        $nb_lines = count($lines);
        $this->buffer = $lines[$nb_lines-1];
        unset($lines[$nb_lines-1]);

        // Here, do your work with the lines you have in the buffer
        var_dump($lines);
        echo '<hr />';

        return strlen($data);
    }
}

Что я делаю:

  • работаю с порциями данных (я использую var_dump, но вместо этого вы будете делать свои обычные вещи), когда они прибудут
  • Обратите внимание, что вы не не получается "полные строки":конец строки - это начало фрагмента, а начало той же строки было в конце предыдущего фрагмента, поэтому вы должны сохранить некоторые части фрагмента между вызовами stream_write


Next , мы регистрируем эту оболочку потока, которая будет использоваться с псевдопротоколом "test":

// Register the wrapper
stream_wrapper_register("test", "MyStream")
    or die("Failed to register protocol");


И теперь мы выполняем наш запрос curl, как и при записи в "настоящий" файл, как и другие предложенные ответы:

// Open the "file"
$fp = fopen("test://MyTestVariableInMemory", "r+");

// Configuration of curl
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "http://www.rue89.com/");
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_BUFFERSIZE, 256);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FILE, $fp);    // Data will be sent to our stream ;-)

curl_exec($ch);

curl_close($ch);

// Don't forget to close the "file" / stream
fclose($fp);

Обратите внимание, что мы работаем не с реальным файлом, а с нашим псевдопротоколом.


Таким образом, каждый раз, когда поступает порция данных, будет вызываться метод MyStream :: stream_write , и сможет работать с небольшим объемом данных (когда я тестировал, у меня всегда было 8192 байта, какое бы значение я ни использовал для CURLOPT_BUFFERSIZE )


Несколько примечаний:

  • Вы нужно проверить это больше, чем я,очевидно
  • моя реализация stream_write, вероятно, не будет работать, если длина строк превышает 8192 байта, которые вы можете исправить; -)
  • Это всего лишь несколько указателей, а не полностью работающее решение: вы должны протестировать (снова) и, возможно, еще немного кода!

Тем не менее, я надеюсь, что это поможет ;-)
Удачи!

51
ответ дан 3 December 2019 в 00:38
поделиться

Вы можете сохранить его во временный файл, а затем читать его по одной строке за раз, используя fgets или fgetcsv .

Таким образом вы избегаете начального большой массив, полученный при взрыве такой большой струны.

5
ответ дан 3 December 2019 в 00:38
поделиться
  1. Увеличьте memory_limit в php.ini .
  2. Прочтите данные с помощью fopen () и fgets ( ) .
3
ответ дан 3 December 2019 в 00:38
поделиться

Спулируйте его в файл. Не пытайтесь сохранить все эти данные в памяти сразу.

2
ответ дан 3 December 2019 в 00:38
поделиться

NB:

«Обычно, если вы открываете файл с помощью fopen, закрываете его, а затем разрываете связь, он работает нормально. Но если между fopen и fclose вы передадите дескриптор файла для cURL, чтобы выполнить некоторую запись в файл, то разорвать связь не удастся. Почему это происходит, я не понимаю. Я думаю, что это может быть связана с ошибкой № 48676 "

http://bugs.php.net/bug.php?id=49517

Так что будьте осторожны, если вы используете старую версию PHP. На этой странице есть простое исправление, позволяющее дважды закрыть файловый ресурс:

fclose($fp);
if (is_resource($fp))
    fclose($fp);
0
ответ дан 3 December 2019 в 00:38
поделиться
Другие вопросы по тегам:

Похожие вопросы: