Fopen не открывает файл из аргументов
]
FOPEN
#include
FILE * fopen (const char * filename, const char * mode);
Opens the file whose name is specified in the parameter filename and associates it with a stream that can be identified in future operations by the FILE pointer returned.
The operations that are allowed on the stream and how these are performed are defined by the mode parameter.
The returned stream is fully buffered by default if it is known to not refer to an interactive device (see setbuf).
The returned pointer can be disassociated from the file by calling fclose or freopen . All opened files are automatically closed on normal program termination.
The running environment supports at least FOPEN_MAX files open simultaneously.
Parameters
filename C string containing the name of the file to be opened.Its value shall follow the file name specifications of the running environment and can include a path (if supported by the system). mode C string containing a file access mode. It can be:
"r" | read: Open file for input operations. The file must exist. |
"w" | write: Create an empty file for output operations. If a file with the same name already exists, its contents are discarded and the file is treated as a new empty file. |
"a" | append: Open file for output at the end of a file. Output operations always write data at the end of the file, expanding it. Repositioning operations (fseek , fsetpos , rewind) are ignored. The file is created if it does not exist. |
"r+" | read/update: Open a file for update (both for input and output). The file must exist. |
"w+" | write/update: Create an empty file and open it for update (both for input and output). If a file with the same name already exists its contents are discarded and the file is treated as a new empty file. |
"a+" | append/update: Open a file for update (both for input and output) with all output operations writing data at the end of the file. Repositioning operations (fseek , fsetpos , rewind) affects the next input operations, but output operations move the position back to the end of file. The file is created if it does not exist. |
The new C standard (C2011, which is not part of C++) adds a new standard subspecifier ("x"), that can be appended to any "w" specifier (to form "wx" , "wbx" , "w+x" or "w+bx"/"wb+x"). This subspecifier forces the function to fail if the file exists, instead of overwriting it.
If additional characters follow the sequence, the behavior depends on the library implementation: some implementations may ignore additional characters so that for example an additional "t" (sometimes used to explicitly state a text file ) is accepted.
On some library implementations, opening or creating a text file with update mode may treat the stream instead as a binary file.
Text files are files containing sequences of lines of text. Depending on the environment where the application runs, some special character conversion may occur in input/output operations in text mode to adapt them to a system-specific text file format. Although on some environments no conversions occur and both text files and binary files are treated the same way, using the appropriate mode improves portability.
For files open for update (those which include a "+" sign), on which both input and output operations are allowed, the stream shall be flushed (fflush) or repositioned (fseek , fsetpos , rewind) before a reading operation that follows a writing operation. The stream shall be repositioned (fseek , fsetpos , rewind) before a writing operation that follows a reading operation (whenever that operation did not reach the end-of-file).
Описание
Функция fopen открывает файл, имя которого указано в параметре fname и связывает его с потоком, который может быть идентифицирован для выполнения различных операций с файлом. Операции с потоком, выполнение которых разрешено определяются параметром modeopen . Cреда программирования поддерживает, по крайней мере, FOPEN_MAX — количество открытых файлов одновременно, где FOPEN_MAX является макро-константа, определенная в
Параметры:
- fname
Си-строка, содержащая имя файла, который необходимо открыть. Этот параметр должен соответствовать правилам именования файлов в используемой системе, и может включать в себя путь, если система поддерживает его. - modeopen
Строка, содержащая режим доступа к файлу. Далее приведён список режимов и их описание:
«r» | Режим открытия файла для чтения. Файл должен существовать. |
«w» | Режим создания пустого файла для записи. Если файл с таким именем уже существует его содержимое стирается, и файл рассматривается как новый пустой файл. |
«a» | Дописать в файл. Операция добавления данных в конец файла. Файл создается, если он не существует. |
«r+» | Режим открытия фала для обновления чтения и записи. Этот файл должен существовать. |
«w+» | Создаёт пустой файл для чтения и записи. Если файл с таким именем уже существует его содержимое стирается, и файл рассматривается как новый пустой файл. |
«a+» | Открыть файл для чтения и добавления данных. Все операции записи выполняются в конец файла, защищая предыдущее содержания файла от случайного изменения. Вы можете изменить позицию (FSEEK , перемотка назад) внутреннего указателя на любое место файла только для чтения, операции записи будет перемещать указатель в конец файла, и только после этого дописывать новую информацию. Файл создается, если он не существует. |
Выше указанные спецификаторы режима доступа к файлу используются только в текстовых файлах. Для того, чтобы открыть двоичный файл, символ b должен быть включен в режим доступа. Этот дополнительный символ b может быть добавлен в конец строки, что даёт следующие режимы доступа к бинарным файлам: rb , wb , ab , r+b , w+b , a+b или может быть вставлен между буквой и знаком + , в случае со смешанными режимами: rb+ , wb+ , ab+ .
В последовательности спецификаторов доступа могут находиться дополнительные символы, хотя они никак не влияют на работу программы. Например, символ ‘ t ‘ иногда прилагается, чтобы показать, что файл является текстовым.
В случае текстовых файлов, в зависимости от среды, в которой работает приложение, некоторые специальные символы преобразования могут в операциях ввода/вывода могут быть адаптированы к системе, из-за специфического формата текстового файла. Во многих системах, например, UNIX-системах, это не имеет значения ни для открытия файла в текстовом режиме ни для открытия файла в двоичном режиме. Оба попадают точно так же, но адаптация служебных символов рекомендуется для лучшей переносимости.
Для смешанных режимов (те, которые включают в себя знак « + »), когда разрешены операции чтения и записи (или добавления), следует обнулить поток функцией fflush или изменить позицию внутреннего указателя (fseek fsetpos , rewind) после операции чтения, за которой следует операция записи и, наоборот, после операции записи, за которой следует операция чтения.
Возвращаемое значение
Если файл был успешно открыт, функция возвращает указатель на объект файла, который используется для идентификации потока и выполнения операций с файлом. В противном случае, возвращается нулевой указатель.
Пример: исходный код программы
//пример использования функции fopen #includeПример работы программы
Записать в только что открытый файл file.txt строку "Пример использования функции fopen" .
В лекции рассмотрен классический способ работы с файлами в C/C++, основанный на библиотеке stdio.h и доступе к данным через структуру FILE . Альтернативный современный механизм работы с файлами в языке C++ на основе потоков и библиотек
Базовые функции для работы с файлами описаны в библиотеке stdio.h . Вся работа с файлом выполняется через файловую переменную - указатель на структуру типа FILE , определённую в стандартной библиотеке:
FILE *fp;
Открыть файл можно функцией fopen , имеющей 2 параметра:
FILE *fopen (char *имя_файла, char *режим_доступа)
Параметр имя_файла может содержать относительный или абсолютный путь к открываемому файлу:
1) "data.txt" - открывается файл data.txt из текущей папки
Важно : при запуске exe-файла "текущая папка" – та, где он находится; при отладке в IDE папка может быть иной, например, в Visual Studio при открытом консольном решении с именем Console файл следует разместить в папке Console/Console , а при запуске исполняемого файла не из IDE – в папке Console/Debug .
2) "f:\\my.dat" - открывается файл my.dat из головной папки диска f:
3) имя файла запрашивается у пользователя:
Char buf; printf ("\nвведите имя файла:"); fflush (stdin); gets (buf);
Параметр режим_доступа определяет, какие действия будут разрешены с открываемым файлом, примеры его возможных значений:
1) "rt" - открываем для чтения текстовый файл;
2) "r+b" - открываем для произвольного доступа (чтение и запись) бинарный файл;
3) "at" – открываем текстовый файл для добавления данных в конец файла;
4) "w" - открываем файл для записи без указания того, текстовый он или бинарный.
Фактически, указание "r" или "t" не накладывает каких-либо ограничений на методы, которые мы будем применять для чтения или записи данных.
После открытия файла следует обязательно проверить, удалась ли эта операция. Для этого есть 2 основных подхода:
1) стандартный обработчик ferror (см. пособиe, п.8.7);
2) сравнить указатель, который вернула fopen , с константой NULL (nullptr) из стандартной библиотеки:
Fp = fopen ("text.txt","r+b"); if (fp==NULL) { //Обработка ситуации "Не удалось открыть файл" }
Пример . Приложение проверяет, удалось ли открыть файл из текущей папки, имя файла запрашивается у пользователя (Visual Studio)
#include
Важно ! Функции, возвращающие указатель, в том числе, fopen , считаются небезопасными в ряде новых компиляторов, например, Visual Studio 2015. Если их использование приводит не просто к предупреждению, а к генерации ошибок, есть 2 основных способа решения проблемы:
FILE *out; fopen_s(&out,"data.txt", "wt");
FILE *out = fopen_s("data.txt", "wt");
2) в начало файла (до всех #include) включить директиву
#define _CRT_SECURE_NO_WARNINGS
Если используется предкомпиляция, то можно определить этот макрос в заголовочном файле stdafx.h .
Выбор способа чтения или записи данных зависит от того, какой должна быть структура файла.
Если файл форматированный , то есть, является текстовым и состоит из лексем, разделённых стандартными разделителями (пробел, табуляция, перевод строки), обмен данными с ним можно выполнять методами:
- fscanf - для чтения
- fprintf - для записи
Первым параметром этих функций указывается файловая переменная, в остальном работа совпадает со стандартными scanf и printf .
Пример . Файл text.txt в текущей папке приложения имеет следующий вид:
1 1.5 -3.5 2 3.5
Прочитаем его как последовательность вещественных чисел.
FILE *fp = fopen ("text.txt","r"); if (fp==NULL) { printf ("\nне удалось открыть файл"); getchar(); exit (1); } float a; while (1) { fscanf (fp,"%f",&a); if (feof(fp)) break; //Если файл кончился, выйти из цикла //здесь выполняется обработка очередного значения a, например: printf ("%.2f ",a); } fclose(fp);
Важно !
1. Функции семейства scanf возвращают целое число - количество значений, которые успешно прочитаны в соответствии с указанным форматом. В реальных приложениях эту величину следует проверять в коде:
Int i=fscanf (fp,"%f",&a); if (i!=1) { //не удалось получить 1 значение }
2. На "восприятие" программой данных может влиять установленная в приложении локаль. Например, если до показанного кода выполнен оператор
Setlocale(LC_ALL,"Rus"); результат работы кода может измениться (для русской локали разделителем целой и дробной части числа является запятая, а не точка).
3. Очередное чтение данных изменяет внутренний файловый указатель . Этот указатель в любой момент времени, пока файл открыт, показывает на следующее значение, которое будет прочитано. Благодаря этому наш код с "бесконечным" while не зациклился.
5. Распространённый в примерах из Сети код вида
While (!feof(fp)) { fscanf (fp,"%f",&a); //обработка числа a }
в ряде компиляторов может породить неточности при интерпретации данных. Например, этот код может прочитать как последнее значение завершающий перевод строки в файле, благодаря чему последнее прочитанное значение "удвоится".
В качестве примера форматной записи в файл сохраним массив a из 10 целочисленных значений в файле с именем result.txt по 5 элементов в строке:
Const int n=10;
int a[n],i;
FILE *fp=fopen ("result.txt","wt");
if (fp==NULL) {
puts ("не удалось открыть файл на запись");
getchar(); exit (1);
}
else {
for (i=0; i Важно
! Ввод/вывод функциями библиотеки stdio.h буферизован
, то есть, данные "пропускаются" через область памяти заданного размера, обмен данными происходит не отдельными байтами, а "порциями". Поэтому перед чтением данных желательно очищать буфер от возможных "остатков" предыдущего чтения методом fflush , а после записи данных следует обязательно закрывать файл методом fclose , иначе данные могут быть потеряны. Заметим, что консольный ввод/вывод "обычными" методами scanf и printf также буферизован. Теперь рассмотрим текстовый файл, состоящий из неструктурированных строк
(абзацев) текста, разделённых символами перевода строки. При работе с такими данными могут потребоваться следующие функции: Как и в случае с функциями для чтения форматированных данных, у всех этих методов имеются аналоги для работы со стандартным вводом/выводом. Пример
. Читая файл, определить длину каждой строки в символах. Для решения задачи воспользуемся тем фактом, что строки завершаются символом "перевод строки" ("\n"). Предполагается, что файл уже открыт для чтения. Int c; int len=0,cnt=0;
while (1) {
c=fgetc(fp);
if (c=="\n") {
printf ("\nString %d, length=%d",++cnt,len); len=0;
}
else len++;
if (feof(fp)) break;
}
if (len) printf ("\nString %d, length=%d",++cnt,len);
Важно
! Из-за особенностей реализации fgetc , без последней проверки за телом цикла код мог "не обратить внимания", например, на последнюю строку файла, состоящую только из пробелов и не завершающуюся переводом строки. Пример
. Читаем построчно файл с известной максимальной длиной строки. Предполагается, что файл уже открыт для чтения. Char buf;
while (1) {
fgets(buf,127,fp);
if (feof(fp)) break;
int len = strlen(buf);
if (buf=="\n") buf="\0";
puts (buf); //Вывести прочитанные строки на экран
}
Важно
! Без дополнительной обработки прочитанные из файла строки при выводе будут содержать лишние пустые строки между строками данных. Это происходит потому, что функция fgets читает строку файла вместе с символом перевода строки (точней, под Windows - с парой символов \r\n , интерпретируемых как один), а puts добавляет к выводимой строке ещё один перевод строки. Если максимальная длина строки принципиально не ограничена, помочь может либо предварительное посимвольное чтение файла для её определения, либо работа с файлом как с бинарными данными.
Бинарный файл
отличается от текстового тем, что необязательно состоит из печатаемых символов со стандартными разделителями между ними. Соответственно, для него не имеет смысла понятие "строки данных", а основной способ работы с ним – чтение и запись наборов байт указанного размера. Основные функции для чтения и записи бинарных данных – fread и fwrite соответственно. В базовой реализации они имеют по 4 параметра: Пример
. Целочисленный массив a запишем в двоичный файл. FILE *fp=fopen ("data.dat","wb");
if (fp==NULL) {
puts ("не удалось открыть файл");
getchar(); exit (1);
}
const int n=10;
int a[n];
for(int i=0; i Учитывая, что данные массива хранятся в последовательно идущих адресах памяти, цикл for для записи мы могли заменить одним оператором: Fwrite (&a,sizeof(int),n,fp);
Подход к чтению данных с помощью fread аналогичен. Например, если файл уже открыт для чтения в режиме "rb": Unsigned char c;
//…
fread (&c,1,1,fp); //читаем по 1 байту
unsigned char buf;
//…
fread (&buf,1,512,fp);
//читаем по 1 сектору - по 512 байт
Для файлов, открытых в режиме "r+b", разрешены и чтение, и запись (произвольный доступ). Поэтому при работе с такими файлами нужны функции позиционирования файлового указателя: Пример
. Определить размер файла в байтах, предположим, что файл уже открыт в режиме чтения или произвольного доступа. Fseek (fp, 0, SEEK_END); //Встали на 0 байт от конца файла
long int pos;
pos = ftell (fp); //Получили текущую позицию в файле
if (pos<0) puts ("\nОшибка");
else if (!pos) puts ("\nФайл пуст");
else printf ("\nВ файле %ld байт",pos);
Материал для чтения из пособия: пп. 8.6-8.11 . Обратите внимание на таблицы с описанными прототипами функций ввода/вывода. Рекомендуемые задачи
: базовое задание включает две задачи, первая из которых предполагает обработку файла как текстовых данных, вторая – как бинарных. В качестве дополнительной третьей задачи может быть предложена реализация одной из задач 1, 2, содержащая консольный интерфейс и меню. Про conio.h и почему его не надо использовать: Для ввода/вывода через цветную консоль во многих источниках используются методы библиотеки conio.h . Следует учитывать, что её реализации в компиляторах от Borland и Microsoft значительно отличаются, а в компиляторах под Unix/Linux реализации conio.h могут отсутствовать. Как вариант, в компиляторах Visual Studio можно использовать аналоги conio.h от сторонних разработчиков, например, открытый проект . Законченный пример кода, реализующего несложное консольное меню для Visual Studio, есть . Предполагается, что к проекту подключены заголовочный файл coniow.h и файл исходного кода coniow.c . fopen()
закрепляет именованый ресурс, указанный в аргументе filename , за потоком. Если filename передан в форме "scheme://...", он считается URL"ом и PHP проведёт поиск обработчика протокола (также известного как "обвёртка") для этой схемы. Если ни одна обвёртка не закреплена за протоколом, PHP выдаст замечание чтобы помочь вам отследить потенциальную проблему в вашем скрипте и продолжит выполнение, будто filename указывает на обыкновенный файл. Если PHP решил, что filename указывает на локальный файл, тогда он попытается открыть поток к этому файлу. Файл должен быть доступен PHP, так что вам следует убедиться, что права доступа на файл разрешают это. Если вы вкдючили безопасный режим или open_basedir , накладываются дальнейшие ограничения. Если PHP решил, что filename указывает на зарегистрированный протокол и этот протокол зарегистрирован как сетевой URL, PHP проверит состояние директивы allow_url_fopen . Если она выключена, PHP выдаст предупреждение и вызов fopen закончится неудачей. Замечание:
Некоторые протоколы поддерживают context и/или опции php.ini . Обратитесь к соответствующей странице с описанием используемого протокола для получения списка опций, которые могут быть установлены. (например, значение php.ini user_agent используется обвёрткой http). Для получения описания параметров contexts и zcontext , обратитесь к разделу Stream Functions . Замечание:
Поддержка контекста была добавленав PHP 5.0.0 . Замечание:
Начиная с версии PHP 4.3.2, бинарный режим является режимом по умолчанию для всех платформ, которые различают бинарный и текстовый, режимы. Если у вас возникли проблемы после обновления, попробуйте использовать флаг "t" в качестве обходного пути до тех пор, пока вы не измените свои скрипты для достижения большей портируемости, как отмечено выше. Параметр mode указывает тип доступа, который вы запрашиваете у потока. Он может быть одним из следующих: Если открыть файл не удалось, функция вернёт FALSE
и сгенерирует ошибку уровня E_WARNING
. Вы можете использовать для того, чтобы подавить это предупреждение. Пример 1. Примеры использования функции fopen()
Если вы сталкиваетесь с проблемами во время чтения или записи файлов, и вы используете PHP в виде серверного модуля, убедитесь в том, что процесс сервера имеет доступ к файлам и директориям, которые вы используете.
resource fopen
(string filename, string mode [, bool use_include_path [, resource zcontext]])
$handle
=
fopen
("/home/rasmus/file.txt"
,
"r"
);
$handle
=
fopen
("/home/rasmus/file.gif"
,
"wb"
);
$handle
=
fopen
("http://www.example.com/"
,
"r"
);
$handle
=
fopen
("ftp://user:[email protected]/somefile.txt"
,
"w"
);
?>