Fopen не создает файл

Обновлено: 06.07.2024

С помощью функции file_get_contents() можно получить содержимое файла:

Также мы можем получить html-код какой-либо страницы в интернете:

Но работает это далеко не для всех сайтов, у многих есть защита от такого примитивного парсинга.

Чтение файла: file()

Функция file() позволяет получить содержимое файла в виде массива. Разделителем элементов является символ переноса строки.

Создадим в корне сайта файл data.txt со следующим содержимым:

Теперь запустим скрипт index.php со следующим кодом:

При запуске этого скрипта мы получим в браузере:

Заметили, что у первых двух строк длина 7 символов вместо пяти? Это из-за того, что каждая строка содержит в конце символы переноса строки.

Чаще всего они нам не нужны, поэтому их можно убрать, передав вторым параметром константу FILE_IGNORE_NEW_LINES :

Теперь у всех строк будет по 5 символов.

Если нам необходимо получить только заполненные строки в файле и пропустить пустые, можно передать вторым параметром константу FILE_SKIP_EMPTY_LINES :

Разумеется, мы можем передать сразу две константы:

Создание файла и запись в файл: file_put_contents()

Функция file_put_contents() позволяет создать файл и заполнить его данными.

Первым параметром функция принимает путь к файлу, вторым - строку с данными. Для создания пустого файла нужно передать вторым параметром пустую строку.

Если файла не существует - он будет создан. Если существует - данные в файле будут перезаписаны.

Чтобы не перезаписывать данные, а добавить их в конец файла, нужно передать третьим параметром константу FILE_APPEND :

Также вторым параметром можно передать массив:

Но этот вариант не очень удобен, поскольку все элементы массива запишутся подряд, без каких-либо разделителей. Чтобы их добавить, можно использовать функцию implode:

Создание папки или структуры папок

Создать папку можно с помощью функции mkdir() (make directory):

Вторым параметром указываются права доступа к файлу в виде восьмеричного числа, по-умолчанию это 0777 , что означает самые широкие права. Для Windows этот аргумент игнорируется.

Кроме этого, второй параметр может игнорироваться при заданной umask (пользовательская маска (user mask), которая нужна для определения конечных прав доступа). В этом случае принудительно сменить права можно функцией chmod() :

Также мы можем создать структуру папок рекурсивно, для этого нужно третьим параметром передать true :

Но в этом случае права доступа будут заданы только для конечной папки. Для изменения прав у каждой из папок придётся указывать права вручную:

Права доступа - это отдельная объёмная тема, поэтому сейчас мы её пока рассматривать не будем.

Проверка существования файла или папки

Проверить существование папки или файла можно с помощью функции file_exists() :

Если вы хотите проверить существование только папки или только файла, для этого есть специальные функции is_dir() и is_file() :

Проверка прав доступа

Функции is_readable() и is_writable() проверяют, есть ли у пользователя, от имени которого запущен PHP, права на чтение и запись файла или папки:

Копирование, перенос и удаление файла

Для удаления файлов используется функция unlink() :

Чтобы скопировать файл, используем функцию copy() :

Для переименования и переноса файла в другую папку используется функция rename() :

Работа с файлами с помощью fopen()

Функций file() , file_get_contents() и file_put_contents() достаточно для решения большинства задач, связанных с управлением файлами.

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

Итак, открыть (или создать и открыть) файл можно с помощью функции fopen() :

Функция fopen() возвращает так называемый лескриптор. Это ссылка, указатель на файл, его мы будем передавать в другие функции. Кстати, тип данных этого дескриптора - resource .

Первым параметром мы передаём путь к файлу, вторым - модификатор доступа к файлу. Ниже перечислены наиболее популярные модификаторы:

  • r - открытие для чтения, указатель переходит в начало файла.
  • r+ - открытие для чтения и записи, указатель переходит в начало файла.
  • w - открытие для записи, указатель переходит в начало файла. Если файла нет - создаётся, если есть - очищается от данных.
  • w+ - открытие для чтения и записи, в остальном аналогичен w .
  • a - открытие для записи, указатель переходит в конец файла. Если файла нет - создаётся.
  • a+ - открытие для чтения и записи, в остальном аналогичен a .
  • x - создание и открытие для записи, указатель переходит в начало файла. Если файл существует - PHP покажет ошибку.
  • x+ - создание и открытие для чтения и записи, в остальном аналогичен x .

Указатель - это нечто вроде курсора. Вы можете переместить его в любое место файла, чтобы добавить или отредактировать определённые данные.

Для записи данных в файл существует функция fwrite() . Давайте попробуем создать файл и записать в него какие-нибудь данные:

Заметьте, из-за модификатора w при каждом запуске скрипта данные в файле стираются и добавляются заново. Если модификатор заменить на a , данные будут не перезаписываться, а добавляться в конец файла.

Для построчного чтения файла используется функция fgets() :

При каждом запуске fgets получает следующую строку и возвращает её в $line . Вторым параметром передаётся максимальная длина строки. Это означает, что если строка слишком длинная, она будет обрезана.

Также в PHP существует множество других полезных функций, работающих с дескриптором файла. Почитать о них можно в документации.

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

Я дважды проверил, что каталог /logs - это chmod 0777, и я даже пошел на дополнительный шаг, переместив его в apache: apache для хорошей меры. Тем не менее, когда сценарий открывает файл, он выдает предупреждение о том, что файл не существует, и вылетает из строя. Файл никогда не создается.

Нужно ли мне подавлять предупреждение fopen() , чтобы заставить его создать файл?

Когда вы работаете с путями в PHP, контекст может иметь большое значение. Если вы работаете с URL-адресами в контексте перенаправления, то корневой каталог ('/') относится к корню вашего домена. То же самое касается путей для связывания файлов или изображений и директив include и require.

Однако, когда вы имеете дело с командами файловой системы, такими как fopen , корневой каталог ('/') является системным корнем. Не корень вашего домена.

Или вы можете использовать $_SERVER['DOCUMENT_ROOT'] , как предлагается в других ответах, для доступа к сохраненному на вашем сервере значению для пути к корню документа. Часть /var/www .

В некоторых случаях вы также можете использовать магическую константу __DIR__ . Обратите внимание, что __DIR__ будет каталогом, в котором находится текущий файл, который не обязательно совпадает с корнем вашего приложения. Так, например, если корень вашего приложения - /var/www/application , а вы работаете в /var/www/application/src/controllers/my_controller.php , то __DIR__ будет /var/www/application/src/controllers . См. здесь, в документации PHP.

Вы пробовали это?

Сервер, на котором вы работаете, мог посадить вас в тюрьму, чтобы вы работали только в каталоге phpapp и его подкаталогах.

Один из способов обойти эту проблему в UBUNTU 14.04 - щелкнуть правой кнопкой мыши каталог, в котором находится файл, и изменить права доступа «других» на «создавать и удалять файлы».

Вы всегда можете открыть свой файл, просто используя "a" , он также создаст новый файл.
Не нужно ставить условие.

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

Путь к файлу должен соответствовать корню сервера. Я мог добиться этого с помощью метода phpinfo () внутри документа, который я хотел знать. Итак, когда вы используете phpinfo (), вы увидите информационный документ. Если вы найдете для _SERVER ["SCRIPT_FILENAME"], вы увидите абсолютный путь к вашему файлу.

Я работаю над тем, что требует PHP для создания файлов и папок. я использую fopen создать файл. Тем не менее, это не похоже на работу. Когда я писал код, я был на Windows с WAMP, и все работало, но когда я переместил сайт на сервер Ubuntu, скрипт просто не работает.

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

Сценарий должен создать папку с идентификатором сеанса, который является случайным числом, и внутри этой папки создать 2 файла и сжать их. Обратите внимание, что папка создана, но не файлы внутри

2 ответа

Вы должны попытаться установить правильные разрешения для каталога.

неправильно, вы должны написать

Ваш скрипт имеет это:

Но это должно быть так; Обратите внимание 0 перед 777 :

Тем не менее, вы должны прочитать о разрешениях PHP и Unix здесь. Как правило, ваши разрешения никогда не должны быть установлены по какой-либо причине на 777 ,

Когда вы устанавливаете разрешения на 777 это означает, что 100% любой, имеющий доступ к вашей машине на любом уровне, может read , write & execute файл. Это означает, что если ваш сайт взломан, то хакер затем использует права на выполнение для запуска сценариев, чтобы глубже проникнуть в вашу систему. Или кто-то еще в системе - так как они могут read , write & execute файл - можно просто удалить ваши файлы, даже не подозревая об этом.

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

Владелец родительского каталога, в котором вы пытаетесь это сделать, должен быть таким же, как пользователь веб-сервера Apache, который обычно www-data на современных системах. Так что родительская папка, которую вы пытаетесь создать $sessionid файл должен принадлежать www-data и имеют read , write & execute набор разрешений, который приравнивается к 7 ,

Более безопасная, разумная и практичная вещь - после того, как у вас установлена ​​проблема с владельцем - это установить разрешения для этой родительской папки на 755 и установите свой mkdir в 0755 а так вот так:

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

  • Первый 6 означает, что владелец файла может read & write к этому.
  • Следующий 4 означает, что члены группы, связанной с этим файлом, могут только read Это.
  • Следующий 4 означает, что другие, которые не являются ни владельцем, ни членом группы, могут read Это.

Что касается 755 они лучше всего подходят для каталогов / папок, потому что каталоги / папки должны иметь execute права, чтобы позволить вам просматривать содержимое внутри них. Так что это ломается так:

Открывает файл. Доступны более безопасные версии этих функций, которые выполняют дополнительные проверки параметров и возвращают коды ошибок. см. раздел fopen_s , _wfopen_s .

Синтаксис

Параметры

mode
Включенный тип доступа.

Возвращаемое значение

Каждая из этих функций возвращает указатель на открытый файл. Значение указателя null обозначает ошибку. Если параметр filename или mode имеет значение NULL или является пустой строкой, эти функции активируют обработчик недопустимых параметров, который описан в разделе Проверка параметров. Если выполнение может быть продолжено, эти функции возвращают значение NULL и задают значение еинвал.

Remarks

fopen Функция открывает файл, указанный параметром filename. По умолчанию строка с узким именем интерпретируется с помощью кодовой страницы ANSI ( CP_ACP ). в Windows классических приложениях это можно изменить на кодовую страницу OEM ( CP_OEMCP ) с помощью SetFileApisToOEM функции. С помощью функции можно AreFileApisANSI определить, интерпретируется ли имя файла с помощью ANSI или системной кодовой страницы OEM по умолчанию. _wfopen — Это версия с расширенными символами fopen ; аргументы для _wfopen представляют собой строки расширенных символов. В противном случае _wfopen fopen поведение идентично. Только использование _wfopen не влияет на закодированную кодировку, используемую в файловом потоке.

fopen принимает пути, допустимые в файловой системе в момент выполнения; fopen принимает пути UNC и пути, которые используют сопоставленные сетевые диски, если система, в которой выполняется код, имеет доступ к общей папке или подключенному диску во время выполнения. При создании путей для fopen Убедитесь, что диски, пути или сетевые папки будут доступны в среде выполнения. В пути в качестве разделителей каталогов можно использовать прямую (/) или обратную (\) косую черту.

Всегда проверяйте возвращаемое значение, чтобы узнать, равен ли указатель NULL, прежде чем выполнять какие-либо дальнейшие операции с файлом. При возникновении ошибки глобальная переменная errno задается и может использоваться для получения конкретных сведений об ошибке. Дополнительные сведения см. в статьях errno ,, _doserrno _sys_errlist и _sys_nerr .

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

Поддержка Юникода

fopen поддерживает файловые потоки в Юникоде. Чтобы открыть файл Юникода, передайте флаг CCS , который задает нужную кодировку fopen , следующим образом.

File * FP = fopen ("newfile.txt", "RT +, CCS =Encoding");

Допустимые значения кодировки : Unicode, UTF-8 и UTF-16LE.

Когда файл открывается в режиме Юникода, входные функции преобразуют данные, считываемые из файла, в данные UTF-16, хранящиеся в виде типа wchar_t . Функции, записывающие в файл, Открытый в режиме Юникода, предполагают буферы, содержащие данные UTF-16, хранящиеся в виде типа wchar_t . Если кодировка файла — UTF-8, при его записи данные UTF-16 преобразуются в UTF-8, а содержимое файла с кодировкой UTF-8 преобразуется в данные UTF-16 при его считывании. Попытка чтения или записи нечетного числа байтов в режиме Юникода приводит к ошибке проверки параметров . Для чтения или записи данных, хранимых в программе в кодировке UTF-8, используйте режим текстового или двоичного файла вместо режима Юникода. Вам необходимо реализовать все обязательные преобразования кодировки.

Если файл уже существует и открыт для чтения или добавления, метка порядка байтов (BOM), если она присутствует в файле, определяет кодирование. Кодировка спецификации имеет приоритет над кодировкой, заданной флагом CCS . Кодировка CCS используется только в том случае, если отсутствует спецификация или файл является новым файлом.

Обнаружение спецификации применяется только к файлам, открываемым в режиме Юникода (то есть путем передачи флага CCS ).

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

Кодирования, используемые на основе CCS-флага и метки BOM

Флаг CCS Нет метки BOM (или новый файл) BOM: UTF-8 BOM: UTF-16
UNICODE UTF-16LE UTF-8 UTF-16LE
UTF-8 UTF-8 UTF-8 UTF-16LE
UTF-16LE UTF-16LE UTF-8 UTF-16LE

В файлы, открытые для записи в режиме Юникода, метка BOM записывается автоматически.

Если mode имеет значение **a, CCS =Encoding * *, fopen сначала пытается открыть файл, используя доступ на чтение и запись. Если это завершается успешно, функция считывает метку BOM, чтобы определить кодировку для файла; если операция завершается сбоем, функция использует для файла кодировку по умолчанию. В любом случае снова fopen открывает файл, используя доступ только для записи. (Это относится только к режиму " a" , а не к режиму "a +" .)

Универсальное текстовое сопоставление функций

Подпрограмма TCHAR.H _UNICODE и _MBCS не определены _MBCS определено _UNICODE определено
_tfopen fopen fopen _wfopen

Режим символьной строки определяет тип доступа, запрашиваемый для файла, как показано ниже.

mode Доступ
Cерверный Открывает для чтения. Если файл не существует или не найден, fopen вызов завершается ошибкой.
Белая Открывает пустой файл для записи. Если указанный файл существует, его содержимое удаляется.
конкретного Открывается для записи в конце файла (добавление) без удаления маркера в конце файла (EOF) перед записью новых данных в файл. Создает файл, если он не существует.
"r +" Открывает для чтения и записи. Файл должен существовать.
"w +" Открывает пустой файл для чтения и записи. Если файл существует, его содержимое удаляется.
"a +" Открывается для чтения и добавления. Операция добавления включает удаления маркера EOF перед записью новых данных в файл. Маркер EOF не восстанавливается по окончании записи. Создает файл, если он не существует.

При открытии файла с помощью типа доступа "a" или типа доступа "a +" все операции записи выполняются в конце файла. Указатель файла может быть перемещен с помощью fseek или rewind , но всегда перемещается обратно в конец файла перед выполнением любой операции записи. Поэтому невозможно перезаписать существующие данные.

Режим "a" не УДАЛЯЕТ маркер EOF перед добавлением к файлу. После добавления команда MS-DOS TYPE отображает данные только до первоначального маркера EOF и не отображает данные, добавленные в файл. Перед добавлением в файл в режиме "a +" удаляется маркер EOF. После добавления команда TYPE MS-DOS отображает все данные в файле. Для добавления в потоковый файл, заканчивающийся маркером EOF CTRL + Z, требуется режим "a +" .

При указании типа доступа "r +", "w +" или "a +" разрешены операции чтения и записи (считается, что файл открыт для обновления). Однако при переходе от чтения к записи операция ввода должна получить маркер конца файла. Если маркер EOF отсутствует, необходимо воспользоваться промежуточным вызовом функции размещения файла. Функции позиционирования файлов: fsetpos , fseek и rewind . При переключении с записи на чтение необходимо использовать промежуточный вызов fflush функции либо в функцию позиционирования файла.

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

Модификатор режима Режим преобразования
t Откройте файл в текстовом (переведенном) режиме.
b Открыть в двоичном (непреобразованном) режиме; переводы, включающие символы возврата каретки и перевода строки, подавляются.

В текстовом режиме CTRL + Z интерпретируется как символ EOF на входе. В файлах, открытых для чтения и записи с помощью "a +", FOPEN проверяет наличие CTRL + Z в конце файла и удаляет его, если это возможно. Это делается потому, что использование fseek и ftell для перемещения в файле, заканчивающемся клавишей CTRL + Z, может привести fseek к неправильному поведению в конце файла.

В текстовом режиме сочетания возврата каретки и перевода строки преобразуются в однострочные каналы ввода, а символы перевода строки преобразуются в сочетания символов возврата каретки и перевода строки на выходе. Если функция ввода-вывода потока Юникода работает в текстовом режиме (по умолчанию) исходный или конечный поток рассматривается как последовательность многобайтовых символов. Поэтому входные функции потока Юникода преобразуют многобайтовые символы в широкие символы (как при вызове mbtowc функции). По той же причине функции потокового вывода в Юникоде преобразуют расширенные символы в многобайтовые символы (как при вызове wctomb функции).

Если t или b не задан в режиме, то режим преобразования по умолчанию определяется глобальной переменной _fmode . Если t или b является префиксом аргумента, функция завершается ошибкой и возвращает значение NULL.

Дополнительные сведения об использовании текстового и двоичного режимов в Юникоде, а также многобайтового потока ввода-вывода см. в статьях Text and Binary Mode File I/O и Ввод-вывод в поток в кодировке Юникод в текстовом и двоичном режиме.

Следующие параметры могут быть добавлены в режим для указания дополнительных поведений.

Модификатор режима Поведение
x Вызывает сбой функции, если имя файла уже существует. Может использоваться только с описателями "w" или "w +".
c Включите флаг фиксации для связанного имени файла , чтобы содержимое файлового буфера записывалось непосредственно на диск при fflush _flushall вызове или.
n Сбросьте флаг фиксации для связанного файла с состоянием "без фиксации". Это значение по умолчанию. Оно также переопределяет глобальный флаг фиксации при соединении программы с COMMODE.OBJ. Значение по умолчанию глобального флага фиксации — без фиксации (no-commit), если только программа не связана явно с файлом COMMODE.OBJ (см. раздел Параметры ссылок).
N Указывает, что файл не наследуется дочерними процессами.
S Указывает, что кэширование оптимизировано для последовательного доступа с диска, но не ограничивается им.
R Указывает, что кэширование оптимизировано для случайного доступа с диска, но не ограничивается им.
T Определяет файл как временный. По возможности он не сбрасывается на диск.
D Определяет файл как временный. Он удаляется, если закрывается последний указатель файла.
CCS =кодирование Задает кодировку, используемую для этого файла (один из UTF-8, UTF-16LE или Unicode). Не указывайте никакое значение, если требуется использовать кодировку ANSI.

Допустимые символы для строки режима , используемой в fopen и _fdopen , соответствуют аргументам офлаг , которые используются в _open и _sopen , как показано ниже.

Символы в строке режима Эквивалентное значение офлаг для _ Open/ _ Сопен
конкретного _ O _ вронли | _ o _ append (обычно _ o _ вронли | _ O _ a | _ o _ append)
a + _ O _ РДВР | _ o _ append (обычно _ O _ РДВР | _ O _ append | _ o _ создание)
r _O _ рдонли
r + _O _ РДВР
w _ O _ вронли (обычно _ o _ вронли | _ o _ создание | _ O _ TRUNC)
w + _ O _ РДВР (обычно _ o _ РДВР | _ o _ создание | _ O _ TRUNC)
b _O _ binary
t _O _ текст
x _O _ без
c None
n None
S _O _ последовательный
R _O _ случайный
T _O _ шортливед
D _O _ временные
CCS = Юникод _O _ втекст
CCS = UTF-8 _O _ UTF8
CCS = UTF-16LE _O _ UTF16

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

Требования

Функция Обязательный заголовок
fopen <stdio.h>
_wfopen <stdio.h> либо <wchar.h>

_wfopen является расширением Microsoft. Дополнительные сведения о совместимости см. в разделе Совместимость.

Параметры режимов c, n, t, S, R, t и D являются расширениями Майкрософт для fopen и _fdopen и не должны использоваться, если требуется переносимость ANSI.

Пример 1

Следующая программа открывает два файла. Он использует fclose , чтобы закрыть первый файл и _fcloseall Закрыть все оставшиеся файлы.

Читайте также: