php чтение всего файла
Запись в файлы и чтение файлов с помощью PHP
В этом уроке вы узнаете несколько важных функций на PHP, которые достаточны для всех ваших основных потребностей чтения и записи файлов. Вы узнаете, как читать файл, записывать в файл, записывать в текстовый файл и проверять, существует ли файл.
К счастью, PHP предоставляет множество функций для чтения и записи данных в файлы. В этом уроке я покажу вам самые простые способы чтения данных из локального или удаленного файла и способы использования флагов для записи в файлы именно так, как мы хотим.
Проверка наличия файла
Ваш первый шаг при попытке чтения данных из файла или записи чего-то в него должен состоять в том, чтобы проверить, существует ли файл уже. Попытка прочитать данные из файла, который не существует, приведет к предупреждению с PHP и, вероятно, приведет к краху вашего кода.
Также важно помнить, что эта функция также вернет false для файлов, которые недоступны из-за ограничений безопасного режима.
Убедимся, что файл фактически существует
Чтение данных из файла в PHP
Запись данных в файл в PHP
Эта функция возвращает количество байтов, которые были записаны в файл с успехом, и false при ошибке. Тем не менее, вы все равно должны использовать строгий оператор равенства, чтобы проверить, было ли успешным запись содержимого в файл. Это потому, что код, который записывает 0 байтов в файл, будет по-прежнему оцениваться как false.
Чтение и запись данных в файлы
Вы также можете сохранить веб-страницы или контент с таких сайтов, как Википедия. Если вам нужно понять HTML или проанализировать содержимое HTML, которое вы только что сохранили локально, вы можете следовать руководству, например, Парсинг HTML на PHP с помощью DiDOM, что поможет вам автоматически получать ссылки, файлы изображений или любую другую такую информацию с веб-страницы.
Вернемся к локальным файлам. Подумайте о ситуации, когда у вас есть куча текстовых файлов, и вы хотите проанализировать их содержимое, чтобы увидеть такие вещи, как самые распространенные слова в них. Этого можно добиться легко, используя кучу встроенных функций PHP.
Это был просто пример автоматического анализа большого количества текста. Вы можете сделать что-то подобное с любым типом текста, хранящегося в файле.
Логирование данных с помощью FILE_APPEND
Подобный код можно использовать для чего-то вроде хранения ежедневной статьи в Википедии в файле каждый день или отслеживания новостных статей и заголовков в течение недель или месяцев. Все, что вам нужно сделать, это написать код, чтобы очистить данные, а затем сохранить их, используя что-то похожее на приведенный выше фрагмент кода. Учебник, подобный Парсингу HTML на PHP при помощи DiDOM может помочь вам.
Вместо того, чтобы писать текст в обычном формате, вы можете обернуть его в некоторый HTML, чтобы упростить чтение в браузерах. Возможности безграничны.
Заключительные мысли
Существует много других способов чтения и записи данных в файлы на PHP. Однако file_get_contents() и file_put_contents() будут решать почти все ваши основные потребности, не добавляя ненужных осложнений.
Работа с файловой системой
Как и большинство языков программирования, PHP поддерживает работу с файлами, которые являются одним из способов хранения информации.
Чтение и запись файлов
Открытие и закрытие файлов
‘r’ : файл открывается только для чтения. Если файла не существует, возвращает false
‘r+’ : файл открывается только для чтения с возможностью записи. Если файла не существует, возвращает false
‘a’ : файл открывается для записи. Если такой файл уже существует, то данные записываются в конец файла, а старые данные остаются. Если файл не существует, то он создается
‘a+’ : файл открывается для чтения и записи. Если файл уже существует, то данные дозаписываются в конец файла. Если файла нет, то он создается
Результатом функции fopen будет дескриптор файла. Этот дескриптор используется для операций с файлом и для его закрытия.
Конструкция or die(«текст ошибки») позволяет прекратить работу скрипта и вывесте некоторое сообщение об ошибке, если функция fopen не смогла открыть файл.
Чтение файла
Чтение файла полностью
Если нам надо прочитать файл полностью, то мы можем облегчить себе жизнь, применив функцию file_get_contents() :
При этом нам не надо открывать явно файл, получать дескриптор, а затем закрывать файл.
Поблочное считывание
Также можно провести поблочное считывание, то есть считывать определенное количество байт из файла с помощью функции fread() :
Функция fread() принимает два параметра: дескриптор считываемого файла и количество считываемых байтов. При считывании блока указатель в файле становится в конец этого блока. И также с помощью функции feof() можно отследить завершение файла.
Запись файла
Аналогично работает другая функция fputs() :
Работа с указателем файла
При открытии файла для чтения или записи в режиме ‘w’, указатель в файле помещается в начало. При считывании данных PHP перемещает указатель в файле в конец блока считанных данных. Однако мы также вручную можем управлять указателем в файле и устанавливать его в произвольное место. Для этого надо использовать функцию fseek, которая имеет следующее формальное определение:
SEEK_SET : значение по умолчанию, устанавливает смещение в offset байт относительно начала файла
SEEK_CUR : устанавливает смещение в offset байт относительно начала текущей позиции в файле
SEEK_END : устанавливает смещение в offset байт от конца файла
Учимся работать с файлами в PHP
В данном уроке мы рассмотрим несколько способов работы с файлами в PHP, а также поговорим о преимуществах и недостатках каждого из них.
Построчное чтение из файла
Для начала давайте научимся читать файлы. Давайте создадим текстовый файл file.txt и запишем в него следующий текст:
Давайте теперь считаем его с помощью программы на языке php. Создайте файл files.php и запишите в него следующий код:
Если вы сейчас запустите этот скрипт, то увидите на экране четверостишие из файла.
Давайте теперь разберём по шагам нашу программу.
Как вы понимаете, для чтения не очень удобно использовать цикл for с указанием конкретного числа строк, которые необходимо считать. Для этого можно использовать функцию feof – она возвращает true, если достигнут конец файла, и false – если нет.
На вход в качестве аргумента она принимает ресурс файла. Программа, переписанная с использованием функции feof будет выглядеть следующим образом:
Цикл будет выполняться до тех пор, пока не достигнут конец файла. При этом функция fgets каждый раз сдвигает курсор на следующую строку. Как только курсор достигнет конца файла, цикл завершится. Таким образом мы не привязаны к числу строк и можем читать файл не задумываясь об этом.
Построчная запись в файл
Теперь запишем данные в файл. Для того чтобы открыть файл для записи используется та же функция fopen, только в качестве режима работы указывается ‘w’ (от write).
А для записи в файл строки используется функция fputs(). Первым аргументом указывается ресурс, а вторым — строка, которую необходимо записать в файл. Давайте в качестве примера напишем программу, которая запишет в файл file2.txt числа от 1 до 100.
Константа PHP_EOL содержит в себе символ переноса строки. При этом для разных операционных систем (Windows или Unix-подобных) эти символы будут разными.
Дозаписываем в конец файла
При этом если сейчас запустить программу снова, то старые данные в файле file2.txt перезапишутся новыми. Для того, чтобы сохранить содержимое файла и дозаписать данные в конец, нужно использовать режим работы с файлом “a” (от append – присоединять, добавлять).
Если мы запустим этот скипт дважды, то в файле file3.txt будет две строки “abc”.
Читаем файл целиком
В PHP также имеется возможность прочитать весь файл за раз. Для этого используется функция file_get_contents().
Данный код выведет всё то же четверостишие, только без переноса строк.
Так произошло потому, что в самом первом примере мы добавляли тег
после каждой прочитанной строки. Если же мы откроем исходный код страницы, то увидим, что на самом деле переносы строк в исходном коде сохранены.
Запись в файл данных целиком
Для того, чтобы записать в файл большой объем данных за раз — сразу несколько строк, можно воспользоваться функцией file_put_contents.
Если снова запустить этот код, файл перезапишется. Для того, чтобы дополнить файл у этой функции есть третий аргумент — режим работы с файлом. Для дозаписи в конец файла следует использовать константу FILE_APPEND.
Какой способ выбрать
Данные способы отличаются в первую очередь тем, что когда мы считываем файл целиком, или записываем в него много данных за раз, нам приходится хранить в оперативной памяти больше данных, чем если бы мы работали по отдельности с каждой строкой. Если данных не слишком много, об этом можно не беспокоиться. Однако, если вы читаете файл размером 10 Гб, а на компьютере, на котором выполняется скрипт, всего 4Гб оперативной памяти, то его получится считать только построчно. При попытке загрузить его целиком программа упадёт с ошибкой о нехватке памяти.
PHP чтение из файла и как его реализовать полегче
Дата публикации: 2017-06-26
От автора: сегодня разберемся, как происходит в PHP чтение из файла. Начнем с легких скриптов и закончим реализацией более сложных. Стартуем!
Полегче
Начнем с рассмотрения функции file_get_contents(). Она «запихивает» содержимое файла в один ряд. Вот так:
Бесплатный курс по PHP программированию
Освойте курс и узнайте, как создать динамичный сайт на PHP и MySQL с полного нуля, используя модель MVC
В курсе 39 уроков | 15 часов видео | исходники для каждого урока
Теперь постараемся реализовать построчное извлечение информации, а не «гурьбой». Для этого применим file(). Данная функция возвращает array строк. Ну, а с массивами (я надеюсь) мы разберемся:
Что-то построчно «вынуть» контент пока не получается. А мы сейчас «ударим» по массиву циклом foreach и array разобьется на нужные «осколки».
Так смотрится намного изящнее.
Посложнее
Начинаем потихоньку «окунаться». Тут главное не начать «зарываться», а то можно застрять надолго. В предыдущих примерах мы только то и делали, что извлекали, извлекали и еще раз извлекали. А если работать с записью нужно? Вооружаемся примером:
Что касается извлечения данных из exel форматов, то тут придется воспользоваться сторонней библиотекой. Но это уже из другого фильма!
Бесплатный курс по PHP программированию
Освойте курс и узнайте, как создать динамичный сайт на PHP и MySQL с полного нуля, используя модель MVC
В курсе 39 уроков | 15 часов видео | исходники для каждого урока
Разработка веб-приложения на PHP
Создайте веб-приложение на PHP на примере приема платежей на сайте
Как прочитать большой файл средствами PHP (не грохнув при этом сервак)
PHP разработчикам не так уж часто приходится следить за расходом памяти в своих приложениях. Сам движок PHP неплохо подчищает мусор за нами, да и модель веб-сервера с контекстом исполнения, «умирающим» после выполнения каждого запроса, позволяет даже самому плохому коду не создавать больших долгих проблем.
Однако, в некоторых ситуациях, мы можем столкнуться с проблемами нехватки оперативной памяти — например, пытаясь запустить композер на маленьком VPS, или при открытии большого файла на сервере не богатом ресурсами.
Последняя проблема и будет рассмотрена в этом уроке.
Мерила Успеха
При проведении любых оптимизаций кода, мы всегда должны замерять результаты его выполнения до и после, для того чтобы оценивать эффективность(или пагубность) наших оптимизаций.
Обычно измеряют загрузку CPU и использование оперативной памяти. Часто бывает, что экономия одного, ведёт к увеличенным затратам другого и наоборот.
В асинхронной модели приложения(мультипроцессорные и многопоточные) всегда очень важно следить как за процессором, так и за памятью. В классических приложениях контроль ресурсов становится проблемой лишь при приближении к лимитам сервера.
Измерять использование CPU внутри PHP плохая идея. Лучше использовать какую-либо утилиту, как top из Ubuntu или macOS. Если вы у вас Windows, то можно использовать Linux Subsystem, чтобы иметь доступ к top.
В этом уроке мы будем измерять использование памяти. Мы посмотрим, как память расходуется в традиционных скриптах, а затем применим парочку фишек для оптимизации и сравним результаты. Надеюсь, к концу статьи, читатель получит базовое понимание основных принципов оптимизации расхода памяти при чтении больших объемов данных.
Будем замерять память так:
Эту функцию мы будем использовать в конце каждого скрипта, и сравнивать полученные значения.
Какие есть варианты?
Существует много разных подходов для эффективного чтения данных, но всех их условно можно разделить на две группы: мы либо считываем и сразу же обрабатываем считанную порцию данных(без предварительной загрузки всех данных в память), либо вовсе преобразуем данные в поток, не заморачиваясь над его содержимым.
Давайте представим, что для первого варианта мы хотим читать файл и отдельно обрабатывать каждые 10000 строк. Нужно будет держать по крайней мере 10000 строк в памяти и передавать их в очередь(в какой бы форме она не была реализована).
Для второго сценария, предположим, мы хотим сжать содержимое очень большого ответа API. Нам не важно, что за данные там содержатся, важно вернуть их в сжатой форме.
В обоих случаях нужно считать большие объемы информации. В первом, нам известен формат данных, во втором, формат значения не имеет. Рассмотрим оба варианта.
Чтение Файла Строка За Строкой
Есть много функций для работы с файлами. Давайте напишем с их помощью свой ридер:
Тут мы считываем файл с работами Шекспира. Размер файла около 5.5MB и пиковое использование памяти 12.8MB.
А теперь, давайте воспользуемся генератором:
Файл тот же, а пиковое использование памяти упало до 393KB! Но пока мы не выполняем со считываемыми данными никаких операций, это не имеет практической пользы. Для примера, мы можем разбивать документ на части, если встретим две пустые строки:
Хотя мы разбили документ на 1,216 кусков, мы использовали лишь 459KB памяти. Всё это, благодаря особенности генераторов — объем памяти для их работы равен размеру самой большой итерируемой части. В данном случае, самая большая часть состоит из 101,985 символов.
Генераторы могут применяться и в других ситуациях, но данный пример хорошо демонстрирует производительность при чтении больших файлов. Возможно, генераторы один из лучших вариантов для обработки данных.
Пайпинг между файлами
В ситуациях, когда обработка данных не требуется, мы можем пробрасывать данные из одного файла в другой. Это называется пайпингом( pipe — труба, возможно потому что мы не видим что происходит внутри трубы, но видим что входит и выходит и неё). Это можно сделать с помощью потоковых методов. Но сперва, давайте напишем классический скрипт, который тупо передает данные из одного файла в другой:
Неудивительно, что этот скрипт использует намного больше памяти, чем занимает копируемый файл. Это связано с тем, что он должен читать и хранить содержимое файла в памяти до тех пор пока файл не будет скопирован полностью. Для маленьких файлов в этом нет ничего страшного, но не для больших.
Давайте попробуем стримить(или пайпить) файлы, один в другой:
Код довольно странный. Мы открываем оба файла, первый на чтение, второй на запись. Затем мы копируем первый во второй, после чего закрываем оба файла. Возможно будет сюрпризом, но мы потратили всего 393KB.
Для того чтобы осуществить задуманное этим способом потребовалось 581KB. Теперь попробуем сделать то же самое с помощью потоков.
Потратили немного меньше памяти(400KB) при одинаковом результате. А если б нам не нужно было сохранять картинку в памяти, мы могли бы сразу застримить её в stdout :
Другие потоки
Существуют и другие потоки, в/из которых можно стримить:
Фильтры
Есть еще одна фишка, которую мы можем использовать — это фильтры. Промежуточный вариант, который дает нам немного контроля над потоком, без необходимости детально погружаться в его содержимое. Допустим, мы хотим сжать файл. Можно применить zip extension:
Хороший код, но он потребляет почти 11MB. С фильтрами, получится лучше:
Здесь мы используем php://filter/zlib.deflate который считывает и сжимает входящие данные. Мы можем пайпить сжатые данные в файл, или куда-нибудь еще. Этот код использовал лишь 896KB.
Я знаю что это не совсем тот же формат, что и zip архив. Но задумайтесь, если у нас есть возможность выбрать иной формат сжатия, затратив в 12 раз меньше памяти, стоит ли это делать?
Чтобы распаковать данные, применим другой zip фильтр.
Вот парочка статей, для тех кому хотелось бы поглубже погрузиться в тему потоков: “Understanding Streams in PHP” и“Using PHP Streams Effectively”.
Кастомизация потоков
fopen и file_get_contents имеют ряд предустановленных опций, но мы можем менять их как душе угодно. Чтобы сделать это, нужно создать новый контекст потока:
В этом примере мы пытаемся сделать POST запрос к API. Прописываем несколько заголовков, и обращаемся к API по файловому дескриптору. Существует много других опций для кастомизации, так что не будет лишним ознакомиться с документацией по этому вопросу.
Создание своих протоколов и фильтров
Перед тем как закончить, давайте поговорим о создании кастомных протоколов. Если посмотреть в документацию, то можно увидеть пример:
Написание своей реализации такого тянет на отдельную статью. Но если все же озадачиться и сделать это, то можно будет легко зарегистрировать свою обертку для стримов:
Аналогичным образом, можно создать и кастомные фильтры потока. Пример класса фильтра из доков:
И его также легко зарегистрировать:
Хотя это не самая частая проблема, с которой мы мучаемся, очень легко накосячить при работе с большими файлами. В асинхронных приложениях, вообще очень просто положить весь сервер, если не контролировать использование памяти в своих скриптах
Надеюсь, что этот урок подарил вам несколько новых идей(или освежил их в памяти) и теперь вы сможете работать с большими файлами гораздо эффективнее. Познакомившись с генераторами и потоками( и перестав использовать функции по типу file_get_contents ) можно избавить наши приложения от целого класса ошибок. That seems like a good thing to aim for!