Открытие файла. Расширение файла C Запись информации в текстовый файл

Текстовые файлы

Рассмотрим работу с текстовым файлом в Си на примере. Создайте на диске С текстовый файл с именем TextFile.txt. Наберите в этом файле такие строки:

String_1 123 String_11, 456
String_2
String_3

Сохраните файл.

А это код программы на C, которая открывает наш файл и считывает из него строки:

/* *Author: @author Subbotin B.P..h> #include #define LEN 50 int main(void) { puts("Text file operations"); char cArray; FILE *pTextFile = fopen("C:\\TextFile.txt", "r"); if(pTextFile == NULL) { puts("Problems"); return EXIT_FAILURE; } while(fgets(cArray, LEN, pTextFile) != NULL) { printf("%s", cArray); } fclose(pTextFile); return EXIT_SUCCESS; }

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

FILE *pTextFile = fopen("C:\\TextFile.txt", "r");

первый аргумент функции fopen указывает на файл, а второй говорит, что файл открыт для чтения из него.

Строки считываем с помощью функции fgets:

fgets(cArray, LEN, pTextFile);

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

После завершения работы с файлом, его надо закрыть:

fclose(pTextFile);

Получаем:

Русские буквы в строках тоже проходят.

Кстати, эту программу я сделал в Eclipse. Как работать с C/C++ в Eclipse можно посмотреть .

Итак, мы открыли и считали данные из текстового файла.

Теперь научимся программно создавать текстовый файл и записывать в него данные.

/* Author: @author Subbotin B.P..h> #include int main(void) { FILE *pTextFile = fopen("C:\\TextFileW.txt", "w"); char *cString = "This is a string"; char cNewLine = "\n"; int nVal = 123; if(pTextFile == NULL) { puts("Problems"); return EXIT_FAILURE; } fprintf(pTextFile, "%s%c", cString, cNewLine); fprintf(pTextFile, "%d", nVal); return EXIT_SUCCESS; }

Создаем текстовый файл для записи в него данных:

FILE *pTextFile = fopen("C:\\TextFileW.txt", "w");

если файл уже имеется, то он будет открыт, и все данные из него будут удалены.

C-строка cString, и число nVal записываются программой в текстовый файл. cNewLine - это просто переход на новую строку.

Записываем данные в текстовый файл с помощью функции fprintf:

fprintf(pTextFile, "%s%c", cString, cNewLine);

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

Функция fopen() открывает для использования поток, связывает файл с данным потоком и затем возвращает указатель FILE на данный поток. Чаще всего файл рас­сматривается как дисковый файл. Функция fopen() имеет следующий прототип:

FILE *fopen(const char *имя_файла, const char *режим);

Где режим указывает на строку, содержащую желаемый режим открытия файла. Допустимые зна­чения для режим в Borland С++ показаны в таблице. имя_файла должно быть строкой симво­лов, предоставляющей корректное имя файла операционной системе, и может содержать указа­ние пути.

Функция fopen() возвращает указатель базового типа FILE. Данный указатель идентифицирует файл и используется большинством функций файловой системы. Его никогда не следует изменять самостоятельно. Функция возвращает нулевой указатель, если файл не может быть открыт.

Как показывает таблица, файл может быть открыт или в текстовом, или в двоичном режи­ме. В текстовом режиме при вводе последовательность возврат каретки и перевод строки трансли­руется в символ новой строки. При выводе справедливо обратное: символ новой строки трансли­руется в возврат каретки и перевод строки. В двоичных файлах такого перевода не происходит. Когда в аргументе режима не указаны ни t, ни b, то статус файла текстовый/двоичный определя­ется значением глобальной переменной _fmode, определенной в Borland С++. По умолчанию fmode установлена в О_ТЕХТ, то есть устанавливается текстовый режим. Если установить _fmode в О_BINARY, то файлы будут открываться в двоичном режиме. (Эти макросы определены в fcntl.h.) Естественно, использование явно указанных t или b устраняет эффекты, связанные с переменной _fmode. Кроме этого, _fmode характерна только для продуктов Borland. Она не определена в системе ввода/вывода ANSI С.

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

Fp = fopen ("test", "w") ;

Где fp - это переменная типа FILE *. Тем не менее обычно можно увидеть следующее:

If((fp = fopen("test", "w"))==NULL) {
puts ("Cannot open file.");
exit (1);
}

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

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

Если необходимо дописать информацию в конец файла, следует использовать режим а (добавления). Если файл не существует, то он будет создан.

Открытие файла на чтение требует наличия файла. Если файл не существует, то будет возвращена ошибка. Если файл открыт для операции чтения/записи, то он не удаляется при наличии, а если файл не существует, то он создается.

Таблица: Допустимые значения режимов

Значение

Открывает файл для чтения. (Открывает по умолчанию как текстовый файл.)

Создает файл для записи. (Открывает по умолчанию как текстовый файл.)

Присоединяет к файлу. (Открывает по умолчанию как текстовый файл.)

Открывает двоичный файл для чтения.

Открывает двоичный файл для записи.

Присоединяет к двоичному файлу.

Открывает файл для чтения/записи. (Открывает по умолчанию как текстовый файл.)

Создает файл для чтения/записи. (Открывает по умолчанию как текстовый файл.)

Присоединяет или создает файл для чтения/записи. (Открывает по умолчанию как текстовый файл.)

Открывает двоичный файл для чтения/записи.

Создает двоичный файл для чтения/записи.

Присоединяет или создает двоичный файл для чтения/записи.

Создает текстовый файл для записи.

Присоединяет к текстовому файлу.

Открывает текстовый файл для чтения.

Создает текстовый файл для чтения/записи.

Открывает или создает текстовый файл для чтения/записи.

Механизм ввода-вывода, разработанный , не соответствует общепринятому сегодня стилю объектно-ориентированного программирования, кроме того, он активно использует операции с указателями, считающиеся потенциально небезопасными в современных защищённых средах выполнения кода. Альтернативой при разработке прикладных приложений является механизм стандартных классов ввода-вывода, предоставляемый стандартом языка C++.

Открытие файлов

Наиболее часто применяются классы ifstream для чтения, ofstream для записи и fstream для модификации файлов.

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

Enum open_mode { app, binary, in, out, trunc, ate };

Ниже приведены возможные значения флагов и их назначение.

Например, чтобы открыть файл с именем test.txt для чтения данных в бинарном виде, следует написать:

Ifstream file; file.open ("test.txt", ios::in | ios::binary);

Оператор логического ИЛИ (|) позволяет составить режим с любым сочетанием флагов. Так, чтобы, открывая файл по записи, случайно не затереть существующий файл с тем же именем, надо использовать следующую форму:

Ofstream file; file.open ("test.txt", ios::out | ios::app);

Предполагается, что к проекту подключён соответствующий заголовочный файл:

#include

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

If (!file) { //Обработка ошибки открытия файла }

Операторы включения и извлечения

Переопределённый в классах работы с файлами оператор включения (<<) записывает данные в файловый поток. Как только вы открыли файл для записи, можно записывать в него текстовую строку целиком:

File << "Это строка текста";

Можно также записывать текстовую строку по частям:

File << "Это " << "строка " << "текста";

Оператор endl завершает ввод строки символом "возврат каретки":

File << "Это строка текста" << endl;

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

Ofstream file ("Temp.txt"); char buff = "Текстовый массив содержит переменные"; int vx = 100; float pi = 3.14159; file << buff << endl << vx << endl << pi << endl;

В результате выполнения кода образуется три строки текстового файла Temp.txt:

Текстовый массив содержит переменные 100 3.14159

Обратите внимание, что числовые значения записываются в файл в виде текстовых строк, а не двоичных значений.

Оператор извлечения (>>)производит обратные действия. Казалось бы, чтобы извлечь символы из файла Temp.txt , записанного ранее, нужно написать код наподобие следующего:

Ifstream file ("Temp.txt"); char buff; int vx; float pi; file >> buff >> vx >> pi;

Однако оператор извлечения остановится на первом попавшемся разделителе (символе пробела, табуляции или новой строки). Таким образом, при разборе предложения "Текстовый массив содержит переменные" только слово "Текстовый" запишется в массив buff , пробел игнорируется, а слово "массив" станет значением целой переменной vx и исполнение кода "пойдет вразнос" с неминуемым нарушением структуры данных. Далее, при обсуждении класса ifstream , будет показано, как правильно организовать чтение файла из предыдущего примера.

Класс ifstream: чтение файлов

Как следует из расшифровки названия, класс ifstream предназначен для ввода файлового потока. Далее перечислены основные методы класса. Большая часть из них унаследована от класса istream и перегружена с расширением родительской функциональности. К примеру, функция get , в зависимости от параметра вызова, способна считывать не только одиночный символ, но и символьный блок.

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

Ifstream file("Temp.txt"); char buff; int vx; float pi; file.getline(buff, sizeof(buff)); file >> vx >> pi:

Метод getline прочитает первую строку файла до конца, а оператор >> присвоит значения переменным.

Следующий пример показывает добавление данных в текстовый файл с последующим чтением всего файла. Цикл while (1) используется вместо while(!file2.eof()) по причинам, которые обсуждались в .

#include #include using namespace std; int main() { ofstream file; file.open("test.txt",ios::out|ios::app); if (!file) { cout << "File error - can"t open to write data!"; cin.sync(); cin.get(); return 1; } for (int i=0; i<10; i++) file << i << endl; file.close(); ifstream file2; file2.open("test.txt", ios::in); if (!file2) { cout << "File error - can"t open to read data!"; cin.sync(); cin.get(); return 2; } int a,k=0; while (1) { file2 >> a; if (file2.eof()) break; cout << a << " "; k++; } cout << endl << "K=" << k << endl; file2.close(); cin.sync(); cin.get(); return 0; }

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

#include #include using namespace std; int main() { ifstream file; // создать поточный объект file file.open("test.txt"); // открыть файл на чтение if (!file) return 1; // возврат по ошибке отрытия char str; // статический буфер строки // Считывать и отображать строки в цикле, пока не eof while (!file.getline(str, sizeof(str)).eof()) cout << str << endl; // вывод прочитанной строки на экран cin.sync(); cin.get(); return 0; }

Этот код под ОС Windows также зависит от наличия в последней строке файла символа перевода строки, надежнее было бы сделать так:

While (1) { if (file.eof()) break; file.getline(str, sizeof(str)); cout << str << endl; }

Явные вызовы методов open и close не обязательны. Действительно, вызов конструктора с аргументом позволяет сразу же, в момент создания поточного объекта file , открыть файл:

Ifstream file("test.txt");

Вместо метода close можно использовать оператор delete , который автоматически вызовет деструктор объекта file и закроет файл. Код цикла while обеспечивает надлежащую проверку признака конца файла.

Класс ofstream: запись файлов

Класс ofstream предназначен для вывода данных из файлового потока. Далее перечислены основные методы данного класса.

Описанный ранее оператор включения удобен для организации записи в текстовый файл:

Ofstream file ("temp.txt"); if (!file) return; for (int i=1; i<=3; i++) file << "Строка " << i << endl; file.close();

Бинарные файлы

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

Первый параметр методов write и read (адрес блока записи/чтения) должен иметь тип символьного указателя char * , поэтому необходимо произвести явное преобразование типа адреса структуры void * . Второй параметр указывает, что бинарные блоки файла имеют постоянный размер байтов независимо от фактической длины записи. Следующее приложение дает пример создания и отображения данных простейшей записной книжки. Затем записи файла последовательно считываются и отображаются на консоли.

#include #include #include using namespace std; struct Notes { // структура данных записной книжки char Name; // Ф.И.О. char Phone; // телефон int Age; // возраст }; int main() { setlocale(LC_ALL, "Russian"); Notes Note1= { "Грозный Иоанн Васильевич", "не установлен", 60 }; Notes Note2= { "Годунов Борис Федорович ", "095-111-2233 ", 30 }; Notes Note3= { "Романов Петр Михайлович ", "812-333-2211 ", 20 }; ofstream ofile("Notebook.dat", ios::binary); ofile.write((char*)&Note1, sizeof(Notes)); // 1-й блок ofile.write((char*)&Note2, sizeof(Notes)); // 2-й блок ofile.write((char*)&Note3, sizeof(Notes)); // 3-й блок ofile.close(); // закрыть записанный файл ifstream ifile("Notebook.dat", ios::binary); Notes Note; // структурированная переменная char str; // статический буфер строки // Считывать и отображать строки в цикле, пока не eof while (!ifile.read((char*)&Note, sizeof(Notes)).eof()) { sprintf(str, "%s\tТел: %s\tВозраст: %d", Note.Name, Note.Phone, Note.Age); cout << str << endl; } ifile.close(); // закрыть прочитанный файл cin.sync(); cin.get(); return 0; }

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

Класс fstream: произвольный доступ к файлу

Предположим что в нашей записной книжке накопилось 100 записей, а мы хотим считать 50-ю. Конечно, можно организовать цикл и прочитать все записи с первой по заданную. Очевидно, что более целенаправленное решение - установить указатель позиционирования файла pos прямо на запись 50 и считать ее:

Ifstream ifile("Notebook.dat", ios::binary); int pos = 49 * sizeof(Notes); ifile.seekg(pos); // поиск 50-й записи Notes Note; //Notes – описанная выше структура "запись" ifile.read((char*)&Note, sizeof(Notes));

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

Ofstream ofilе ("Notebook.dat", ios::binary | ios::ate); int pos = 49 * sizeof(Notes); ofile seekp(pos); // поиск 50-й записи Notes Note50 = {"Ельцин Борис Николаевич", "095-222-3322", 64}; ofile.write((char*)&Note, sizeof(Notes)); // замена

Если не указать флаг ios::ate (или ios::app), то при открытии бинарного файла Notebook.dat его предыдущее содержимое будет стерто!

Наконец, можно открыть файл одновременно для чтения/записи, используя методы, унаследованные поточным классом fstream от своих предшественников. Поскольку класс fstream произведен от istream и ostream (родителей ifstream и ofstream соответственно), все упомянутые ранее методы становятся доступными в приложении.

В следующем примере показана перестановка первой и третьей записей файла Notebook.dat .

#include #include #include using namespace std; struct Notes { char Name; char Phone; int Age; }; int main() { setlocale(LC_ALL, "Russian"); Notes Note1, Note3; // Открыть файл на чтение/запись одновременно fstream file("Notebook.dat", ios::binary | ios::in | ios::out); file.seekg(2 * sizeof(Notes)); // найти и считать Note3 file.read((char*)&Note3, sizeof(Notes)); file.seekg(0); // найти и считать Note1 file.read((char*)&Note1, sizeof(Notes)); file.seekg(0); // Note1 <== Note3 file.write((char*)&Note3, sizeof(Notes)); file.seekg(2 * sizeof(Notes)); // Note3 <== Note1 file.write((char*)&Note1, sizeof(Notes)); char str; // Считывать и отображать записи в цикле, пока не eof file.seekg(0); // вернуться к началу файла while (!file.read((char*)&Note1, sizeof(Notes)).eof()) { sprintf(str, "%s\tТел: %s\tВозраст: %d", Note1.Name, Note1.Phone, Note1.Age); cout << str << endl; } file.close(); cin.sync(); cin.get(); return 0; }

В конструкторе объекта file надо указать флаги ios::in и ios::out , разрешая одновременное выполнение операций чтения и записи. В результате выполнения этого кода первая и третья записи бинарного файла Notebook.dat поменяются местами.

Дополнительные примеры по теме есть .

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

Что еще может вызвать проблемы?

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

Вы хотите помочь?

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

Случайные статьи

Вверх