Зачем мне нужен `fclose` после записи в файл на PHP?

#php

#php

Вопрос:

Почему мне нужно завершить работу с помощью fclose($handle) функции после записи в файл с использованием php? Разве программа не делает это автоматически, когда она завершается?

Комментарии:

1. ДА. PHP автоматически закрывает дескрипторы файлов при завершении работы скрипта. Однако в любых ситуациях, когда скрипт не будет немедленно завершаться после ввода-вывода файла, вероятно, хорошей идеей будет закрыть файл. например, если вы пишете библиотеку, и эта библиотека используется скриптом CLI, который сотни раз вызывает вашу библиотечную функцию, лучше закрыть файл после каждого вызова.

2. @Frank, это должен был быть ответ, чтобы за него можно было проголосовать. 🙂

Ответ №1:

ДА. Но рекомендуется делать это самостоятельно. Кроме того, вы оставите файл открытым во время всего выполнения остальной части скрипта, чего вам следует избегать. Таким образом, если ваш скрипт не завершит выполнение сразу после того, как вы закончите писать, вы, по сути, оставляете файл открытым дольше, чем вам нужно.

Комментарии:

1. Разве это плохо — оставлять его открытым? Каковы недостатки в том, чтобы оставить его открытым?

2. Вы используете больше памяти, и другие процессы могут быть не в состоянии использовать этот файл.

3. Вам нужно подкрепить свое утверждение ссылкой на php.net руководство пользователя или исходный код интерпретатора.

4. Также существуют ограничения на количество дескрипторов открытых файлов, разрешенных O / S, поэтому, если вы перебираете тысячи файлов, ваш PHP-скрипт в конечном итоге (вероятно) завершится сбоем, если вы не закроете файлы, когда закончите с ними.

Ответ №2:

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

Явным вызовом fclose() и проверкой его возвращаемого значения у вас есть возможность:

  • Повторите операцию
  • Разверните изменения
  • Возвращает условие сбоя вызывающей функции
  • Сообщите о проблеме пользователю
  • Задокументируйте проблему в файле журнала
  • Возвращает индикацию сбоя в среду выполнения (такую как оболочка командной строки), которая может иметь решающее значение при использовании в цепочке инструментов.

или каким-либо другим способом, который соответствует вашей ситуации.

Это упоминается в разделе комментариев на fclose() странице руководства.

Ответ №3:

Оставлять файловые дескрипторы открытыми также имеет последствия для безопасности: http://cwe.mitre.org/data/definitions/403.html

Ваша программа может выполнять программу с разными уровнями привилегий, а утечка файлового дескриптора может позволить частной информации пересечь границу между процессами с двумя разными уровнями доверия:

http://osvdb.org/7559
CVE-2006-5397
CVE-2007-5159
CVE-2008-3914

Забавная вещь с ошибками безопасности заключается в том, что это может быть совершенно безопасно, когда вы пишете начальную функцию, но год или два спустя может стать небезопасным из-за невинно выглядящего изменения.

Ответ №4:

Да, PHP обычно закрывает файл перед выходом. Но вы всегда должны закрывать его вручную:

1 — Это хорошая практика программирования

2- PHP может неожиданно завершиться (например, неперехваченное исключение). Это может оставить файл с чем-то в очереди на запись или с блокировкой в нем.

Комментарии:

1. Я ожидал бы, что неперехваченное исключение все равно очистит дескрипторы файлов. Тем не менее, я, безусловно, видел PHP segfault более нескольких раз, и PHP никак не может выполнить какую-либо очистку в этой ситуации

Ответ №5:

За исключением случаев, когда программа не завершается или занимает много времени, это относится к максимальным дескрипторам открытых файлов в системе. Но да, PHP допускает лень.

Ответ №6:

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

Ответ №7:

Когда файл открывается, на него накладывается блокировка, не позволяющая другим процессам использовать его. fclose() удаляет эту блокировку.

$handle это не объект, просто указатель. Таким образом, нет деструктора, указывающего ему разблокировать.

Комментарии:

1. Я немного запутался в ваших местоимениях здесь. Когда вы говорите, что на него наложена блокировка, вы имеете в виду, что блокировка наложена на файл? Если да, то какое отношение блокировка имеет к использованию функции? Что делает блокировка?

2. блокировка помещается на файл. если вы выполняете запись в файл, а затем появляется другой процесс и пытается записать файл — доступ будет запрещен, потому что две разные вещи не могут записывать в файл одновременно. блокировка не позволяет второму процессу выполнять запись.

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

4. Нет, любой процесс, записывающий в файл, получает блокировку, так что другой процесс не может выполнить запись в файл. Если вы открываете файл, он блокируется, если что-то еще пытается записать в этот файл, второму процессу записи приходится ждать, пока файл не будет выпущен / разблокирован — что достигается с помощью fclose. Чем скорее вы закроете свой файл и снимете блокировку, тем скорее что-то другое сможет снова выполнить запись в этот файл.

5. -1, фактически неверно. PHP не автоматически устанавливает блокировки на файлы. Если вы хотите или нуждаетесь в блокировке, вы должны явно запросить блокировку во время или сразу после открытия. Кроме того, в последних точечных выпусках PHP теперь требуется, чтобы вы явно снимали блокировку перед закрытием , в то время как ранее блокировка снималась с помощью fclose alone.