Какое действие выполняется при открытии файла
Перейти к содержимому

Какое действие выполняется при открытии файла

  • автор:

Ввод данных из файла и вывод в файл

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

В языке программирования C указатель на файл имеет тип FILE и его объявление выглядит так:

FILE *myfile;

С другой стороны, функция fopen() открывает файл по указанному в качестве первого аргумента адресу в режиме чтения («r»), записи («w») или добавления («a») и возвращает в программу указатель на него. Поэтому процесс открытия файла и подключения его к программе выглядит примерно так:

myfile = fopen("hello.txt", "r");

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

При чтении или записи данных в файл обращение к нему осуществляется посредством файлового указателя (в данном случае, myfile).

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

Объявление функции fopen() содержится в заголовочном файле stdio.h, поэтому требуется его подключение. Также в stdio.h объявлен тип-структура FILE.

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

fclose(myfile);

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

Чтение из текстового файла и запись в него

fscanf()

Функция fscanf() аналогична по смыслу функции scanf() , но в отличии от нее осуществляет форматированный ввод из файла, а не стандартного потока ввода. Функция fscanf() принимает параметры: файловый указатель, строку формата, адреса областей памяти для записи данных:

fscanf(myfile, "%s%d", str, &a); 

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

Допустим, у нас есть файл содержащий такое описание объектов:

apples 10 23.4 bananas 5 25.0 bread 1 10.3

Тогда, чтобы считать эти данные, мы можем написать такую программу:

#include int main () { FILE *file; struct food { char name[20]; unsigned qty; float price; }; struct food shop[10]; char i=0; file = fopen("fscanf.txt", "r"); while (fscanf(file, "%s%u%f", shop[i].name, &(shop[i].qty), &(shop[i].price)) != EOF) { printf("%s %u %.2f\n", shop[i].name, shop[i].qty, shop[i].price); i++; } }

В данном случае объявляется структура и массив структур. Каждая строка из файла соответствует одному элементу массива; элемент массива представляет собой структуру, содержащую строковое и два числовых поля. За одну итерацию цикл считывает одну строку. Когда встречается конец файла fscanf() возвращает значение EOF и цикл завершается.

fgets()

Функция fgets() аналогична функции gets() и осуществляет построчный ввод из файла. Один вызов fgets() позволят прочитать одну строку. При этом можно прочитать не всю строку, а лишь ее часть от начала. Параметры fgets() выглядят таким образом:

fgets(массив_символов, количество_считываемых_символов, указатель_на_файл)
fgets(str, 50, myfile)

Такой вызов функции прочитает из файла, связанного с указателем myfile, одну строку текста полностью, если ее длина меньше 50 символов с учетом символа ‘\n’, который функция также сохранит в массиве. Последним (50-ым) элементом массива str будет символ ‘\0’, добавленный fgets() . Если строка окажется длиннее, то функция прочитает 49 символов и в конце запишет ‘\0’. В таком случае ‘\n’ в считанной строке содержаться не будет.

#include #define N 80 main () { FILE *file; char arr[N]; file = fopen("fscanf.txt", "r"); while (fgets(arr, N, file) != NULL) printf("%s", arr); printf("\n"); fclose(file); }

В этой программе в отличие от предыдущей данные считываются строка за строкой в массив arr. Когда считывается следующая строка, предыдущая теряется. Функция fgets() возвращает NULL в случае, если не может прочитать следующую строку.

getc() или fgetc()

Функция getc() или fgetc() (работает и то и другое) позволяет получить из файла очередной один символ.

#include #define N 80 int main () { FILE *file; char arr[N]; int i; file = fopen("fscanf.txt", "r"); while ((arr[i] = fgetc(file)) != EOF) { if (arr[i] == '\n') { arr[i] = '\0'; printf("%s\n",arr); i = 0; } else i++; } arr[i] = '\0'; printf("%s\n",arr); fclose(file); }

Приведенный в качестве примера код выводит данные из файла на экран.

Запись в текстовый файл

Также как и ввод, вывод в файл может быть различным.

  • Форматированный вывод. Функция fprintf ( файловый_указатель, строка_формата, переменные ) .
  • Посточный вывод. Функция fputs ( строка, файловый_указатель ) .
  • Посимвольный вывод. Функция fputc() или putc( символ, файловый_указатель ) .

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

Запись в каждую строку файла полей одной структуры:

#include int main () { FILE *file; struct food { char name[20]; unsigned qty; float price; }; struct food shop[10]; char i=0; file = fopen("fprintf.txt", "w"); while (scanf("%s%u%f", shop[i].name, &(shop[i].qty), &(shop[i].price)) != EOF) { fprintf(file, "%s %u %.2f\n", shop[i].name, shop[i].qty, shop[i].price); i++; } fclose(file); }

Построчный вывод в файл ( fputs() , в отличие от puts() сама не помещает в конце строки ‘\n’):

while (gets(arr) != NULL) { fputs(arr, file); fputs("\n", file); }

Пример посимвольного вывода:

while ((i = getchar()) != EOF) putc(i, file);

Чтение из двоичного файла и запись в него

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

При открытии файла для двоичного доступа, вторым параметром функции fopen() является строка «rb» или «wb».

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

Функции fread() и fwrite() принимают в качестве параметров:

  1. адрес области памяти, куда данные записываются или откуда считываются,
  2. размер одного данного какого-либо типа,
  3. количество считываемых данных указанного размера,
  4. файловый указатель.

Эти функции возвращают количество успешно прочитанных или записанных данных. Т.е. можно «заказать» считывание 50 элементов данных, а получить только 10. Ошибки при этом не возникнет.

Пример использования функций fread() и fwrite() :

#include #include int main () { FILE *file; char shelf1[50], shelf2[100]; int n, m; file = fopen("shelf1.txt", "rb"); n=fread(shelf1, sizeof(char), 50, file); fclose(file); file = fopen("shelf2.txt", "rb"); m=fread(shelf2, sizeof(char), 50, file); fclose(file); shelf1[n] = '\0'; shelf2[m] = '\n'; shelf2[m+1] = '\0'; file = fopen("shop.txt", "wb"); fwrite(strcat(shelf2,shelf1), sizeof(char), n+m, file); fclose(file); }

Здесь осуществляется попытка чтения из первого файла 50-ти символов. В n сохраняется количество реально считанных символов. Значение n может быть равно 50 или меньше. Данные помещаются в строку. То же самое происходит со вторым файлом. Далее первая строка присоединяется ко второй, и данные сбрасываются в третий файл.

  1. Напишите программу, которая запрашивает у пользователя имя (адрес) текстового файла, далее открывает его и считает в нем количество символов и строк.
  2. Напишите программу, которая записывает в файл данные, полученные из другого файла и так или иначе измененные перед записью. Каждая строка данных, полученная из файла, должна помещаться в структуру.

Курс с решением части задач:
pdf-версия

Работа с файлами в С++

Большинство компьютерных программ работают с файлами, и поэтому возникает необходимость создавать, удалять, записывать читать, открывать файлы. Что же такое файл? Файл – именованный набор байтов, который может быть сохранен на некотором накопителе. Ну, теперь ясно, что под файлом понимается некоторая последовательность байтов, которая имеет своё, уникальное имя, например файл.txt . В одной директории не могут находиться файлы с одинаковыми именами. Под именем файла понимается не только его название, но и расширение, например: file.txt и file.dat разные файлы, хоть и имеют одинаковые названия. Существует такое понятие, как полное имя файлов – это полный адрес к директории файла с указанием имени файла, например: D:\docs\file.txt . Важно понимать эти базовые понятия, иначе сложно будет работать с файлами.

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

Файловый ввод/вывод аналогичен стандартному вводу/выводу, единственное отличие – это то, что ввод/вывод выполнятся не на экран, а в файл. Если ввод/вывод на стандартные устройства выполняется с помощью объектов cin и cout , то для организации файлового ввода/вывода достаточно создать собственные объекты, которые можно использовать аналогично операторам cin и cout .

Например, необходимо создать текстовый файл и записать в него строку Работа с файлами в С++ . Для этого необходимо проделать следующие шаги:

  1. создать объект класса ofstream ;
  2. связать объект класса с файлом, в который будет производиться запись;
  3. записать строку в файл;
  4. закрыть файл.

Почему необходимо создавать объект класса ofstream , а не класса ifstream ? Потому, что нужно сделать запись в файл, а если бы нужно было считать данные из файла, то создавался бы объект класса ifstream .

// создаём объект для записи в файл ofstream /*имя объекта*/; // объект класса ofstream

Назовём объект – fout , Вот что получится:

ofstream fout;

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

fout.open("cppstudio.txt"); // связываем объект с файлом

Через операцию точка получаем доступ к методу класса open(), в круглых скобочках которого указываем имя файла. Указанный файл будет создан в текущей директории с программой. Если файл с таким именем существует, то существующий файл будет заменен новым. Итак, файл открыт, осталось записать в него нужную строку. Делается это так:

fout 

Используя операцию передачи в поток совместно с объектом fout строка Работа с файлами в С++ записывается в файл. Так как больше нет необходимости изменять содержимое файла, его нужно закрыть, то есть отделить объект от файла.

fout.close(); // закрываем файл

Итог – создан файл со строкой Работа с файлами в С++ .

Шаги 1 и 2 можно объединить, то есть в одной строке создать объект и связать его с файлом. Делается это так:

ofstream fout("cppstudio.txt"); // создаём объект класса ofstream и связываем его с файлом cppstudio.txt

Объединим весь код и получим следующую программу.

// file.cpp: определяет точку входа для консольного приложения. #include "stdafx.h" #include using namespace std; int main(int argc, char* argv[]) < ofstream fout("cppstudio.txt"); // создаём объект класса ofstream для записи и связываем его с файлом cppstudio.txt fout 

Осталось проверить правильность работы программы, а для этого открываем файл cppstudio.txt и смотрим его содержимое, должно быть — Работа с файлами в С++ .

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

  1. создать объект класса ifstream и связать его с файлом, из которого будет производиться считывание;
  2. прочитать файл;
  3. закрыть файл.
// file_read.cpp: определяет точку входа для консольного приложения. #include "stdafx.h" #include #include using namespace std; int main(int argc, char* argv[]) < setlocale(LC_ALL, "rus"); // корректное отображение Кириллицы char buff[50]; // буфер промежуточного хранения считываемого из файла текста ifstream fin("cppstudio.txt"); // открыли файл для чтения fin >> buff; // считали первое слово из файла cout 

В программе показаны два способа чтения из файла, первый – используя операцию передачи в поток, второй – используя функцию getline() . В первом случае считывается только первое слово, а во втором случае считывается строка, длинной 50 символов. Но так как в файле осталось меньше 50 символов, то считываются символы включительно до последнего. Обратите внимание на то, что считывание во второй раз ( строка 17 ) продолжилось, после первого слова, а не с начала, так как первое слово было прочитано в строке 14 . Результат работы программы показан на рисунке 1.

CppStudio.com

Работа с файлами в С++ Для продолжения нажмите любую клавишу . . .

Рисунок 1 — Работа с файлами в С++

Программа сработала правильно, но не всегда так бывает, даже в том случае, если с кодом всё впорядке. Например, в программу передано имя несуществующего файла или в имени допущена ошибка. Что тогда? В этом случае ничего не произойдёт вообще. Файл не будет найден, а значит и прочитать его не возможно. Поэтому компилятор проигнорирует строки, где выполняется работа с файлом. В результате корректно завершится работа программы, но ничего, на экране показано не будет. Казалось бы это вполне нормальная реакции на такую ситуацию. Но простому пользователю не будет понятно, в чём дело и почему на экране не появилась строка из файла. Так вот, чтобы всё было предельно понятно в С++ предусмотрена такая функция — is_open() , которая возвращает целые значения: 1 — если файл был успешно открыт, 0 — если файл открыт не был. Доработаем программу с открытием файла, таким образом, что если файл не открыт выводилось соответствующее сообщение.

// file_read.cpp: определяет точку входа для консольного приложения. #include "stdafx.h" #include #include using namespace std; int main(int argc, char* argv[]) < setlocale(LC_ALL, "rus"); // корректное отображение Кириллицы char buff[50]; // буфер промежуточного хранения считываемого из файла текста ifstream fin("cppstudio.doc"); // (ВВЕЛИ НЕ КОРРЕКТНОЕ ИМЯ ФАЙЛА) if (!fin.is_open()) // если файл не открыт cout > buff; // считали первое слово из файла cout system("pause"); return 0; >

Результат работы программы показан на рисунке 2.

CppStudio.com

Файл не может быть открыт! Для продолжения нажмите любую клавишу . . .

Рисунок 2 — Работа с файлами в С++

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

Режимы открытия файлов

Режимы открытия файлов устанавливают характер использования файлов. Для установки режима в классе ios_base предусмотрены константы, которые определяют режим открытия файлов (см. Таблица 1).

Таблица 1 — режимы открытия файлов

Константа Описание
ios_base::in открыть файл для чтения
ios_base::out открыть файл для записи
ios_base::ate при открытии переместить указатель в конец файла
ios_base::app открыть файл для записи в конец файла
ios_base::trunc удалить содержимое файла, если он существует
ios_base::binary открытие файла в двоичном режиме

Режимы открытия файлов можно устанавливать непосредственно при создании объекта или при вызове функции open() .

ofstream fout("cppstudio.txt", ios_base::app); // открываем файл для добавления информации к концу файла fout.open("cppstudio.txt", ios_base::app); // открываем файл для добавления информации к концу файла

Режимы открытия файлов можно комбинировать с помощью поразрядной логической операции или | , например: ios_base::out | ios_base::trunc — открытие файла для записи, предварительно очистив его.

Объекты класса ofstream , при связке с файлами по умолчанию содержат режимы открытия файлов ios_base::out | ios_base::trunc . То есть файл будет создан, если не существует. Если же файл существует, то его содержимое будет удалено, а сам файл будет готов к записи. Объекты класса ifstream связываясь с файлом, имеют по умолчанию режим открытия файла ios_base::in — файл открыт только для чтения. Режим открытия файла ещё называют — флаг, для удобочитаемости в дальнейшем будем использовать именно этот термин. В таблице 1 перечислены далеко не все флаги, но для начала этих должно хватить.

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

Разработаем программу, которая, используя операцию sizeof() , будет вычислять характеристики основных типов данных в С++ и записывать их в файл. Характеристики:

  1. число байт, отводимое под тип данных
  2. максимальное значение, которое может хранить определённый тип данных.

Запись в файл должна выполняться в таком формате:

/* data type byte max value bool = 1 255.00 char = 1 255.00 short int = 2 32767.00 unsigned short int = 2 65535.00 int = 4 2147483647.00 unsigned int = 4 4294967295.00 long int = 4 2147483647.00 unsigned long int = 4 4294967295.00 float = 4 2147483647.00 long float = 8 9223372036854775800.00 double = 8 9223372036854775800.00 */

Такая программа уже разрабатывалась ранее в разделе Типы данных С++ , но там вся информация о типах данных выводилась на стандартное устройство вывода, а нам необходимо программу переделать так, чтобы информация записывалась в файл. Для этого необходимо открыть файл в режиме записи, с предварительным усечением текущей информации файла (строка 14). Как только файл создан и успешно открыт (строки 16 — 20), вместо оператора cout , в строке 22 используем объект fout . таким образом, вместо экрана информация о типах данных запишется в файл.

// write_file.cpp: определяет точку входа для консольного приложения. #include "stdafx.h" #include #include // работа с файлами #include // манипуляторы ввода/вывода using namespace std; int main(int argc, char* argv[]) < setlocale(LC_ALL, "rus"); // связываем объект с файлом, при этом файл открываем в режиме записи, предварительно удаляя все данные из него ofstream fout("data_types.txt", ios_base::out | ios_base::trunc); if (!fout.is_open()) // если файл небыл открыт < cout fout << " data type " << "byte" << " " << " max value " << endl // заголовки столбцов << "bool = " << sizeof(bool) << " " << fixed << setprecision(2) /*вычисляем максимальное значение для типа данных bool*/ << (pow(2,sizeof(bool) * 8.0) - 1) << endl << "char = " << sizeof(char) << " " << fixed << setprecision(2) /*вычисляем максимальное значение для типа данных char*/ << (pow(2,sizeof(char) * 8.0) - 1) << endl << "short int = " << sizeof(short int) << " " << fixed << setprecision(2) /*вычисляем максимальное значение для типа данных short int*/ << (pow(2,sizeof(short int) * 8.0 - 1) - 1) << endl << "unsigned short int = " << sizeof(unsigned short int) << " " << fixed << setprecision(2) /*вычисляем максимальное значение для типа данных unsigned short int*/ << (pow(2,sizeof(unsigned short int) * 8.0) - 1) << endl << "int = " << sizeof(int) << " " << fixed << setprecision(2) /*вычисляем максимальное значение для типа данных int*/ << (pow(2,sizeof(int) * 8.0 - 1) - 1) << endl << "unsigned int = " << sizeof(unsigned int) << " " << fixed << setprecision(2) /*вычисляем максимальное значение для типа данных unsigned int*/ << (pow(2,sizeof(unsigned int) * 8.0) - 1) << endl << "long int = " << sizeof(long int) << " " << fixed << setprecision(2) /*вычисляем максимальное значение для типа данных long int*/ << (pow(2,sizeof(long int) * 8.0 - 1) - 1) << endl << "unsigned long int = " << sizeof(unsigned long int) << " " << fixed << setprecision(2) /*вычисляем максимальное значение для типа данных undigned long int*/ << (pow(2,sizeof(unsigned long int) * 8.0) - 1) << endl << "float = " << sizeof(float) << " " << fixed << setprecision(2) /*вычисляем максимальное значение для типа данных float*/ << (pow(2,sizeof(float) * 8.0 - 1) - 1) << endl << "long float = " << sizeof(long float) << " " << fixed << setprecision(2) /*вычисляем максимальное значение для типа данных long float*/ << (pow(2,sizeof(long float) * 8.0 - 1) - 1) << endl << "double = " << sizeof(double) << " " << fixed << setprecision(2) /*вычисляем максимальное значение для типа данных double*/ << (pow(2,sizeof(double) * 8.0 - 1) - 1) << endl; fout.close(); // программа больше не использует файл, поэтому его нужно закрыть cout

Нельзя не заметить, что изменения в программе минимальны, а всё благодаря тому, что стандартный ввод/вывод и файловый ввод/вывод используются абсолютно аналогично. В конце программы, в строке 45 мы явно закрыли файл, хотя это и не обязательно, но считается хорошим тоном программирования. Стоит отметить, что все функции и манипуляторы используемые для форматирования стандартного ввода/вывода актуальны и для файлового ввода/вывода. Поэтому не возникло никаких ошибок, когда оператор cout был заменён объектом fout .

Основы работы с файлами в Python

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

Михаил Свинцов
автор курса «Full-stack веб-разработчик на Python»

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

Встроенные средства Python

Основа для работы с файлами — built-in функция open()

open(file, mode="rt") 

Эта функция имеет два аргумента. Аргумент file принимает строку, в которой содержится путь к файлу. Второй аргумент, mode , позволяет указать режим, в котором необходимо работать с файлом. По умолчанию этот аргумент принимает значение «rt», с которым, и с некоторыми другими, можно ознакомиться в таблице ниже

Эти режимы могут быть скомбинированы. Например, «rb» открывает двоичный файл для чтения. Комбинируя «r+» или «w+» можно добиться открытия файла в режиме и чтения, и записи одновременно с одним отличием — первый режим вызовет исключение, если файла не существует, а работа во втором режиме в таком случае создаст его.

Начать саму работу с файлом можно с помощью объекта класса io.TextIOWrapper , который возвращается функцией open() . У этого объекта есть несколько атрибутов, через которые можно получить информацию

  • name — название файла;
  • mode — режим, в котором этот файл открыт;
  • closed — возвращает True , если файл был закрыт.

По завершении работы с файлом его необходимо закрыть при помощи метода close()

f = open("examp.le", "w") // работа с файлом f.close() 

Однако более pythonic way стиль работы с файлом встроенными средствами заключается в использовании конструкции with .. as .. , которая работает как менеджер создания контекста. Написанный выше пример можно переписать с ее помощью

with open("examp.le", "w") as f: // работа с файлом 

Главное отличие заключается в том, что python самостоятельно закрывает файл, и разработчику нет необходимости помнить об этом. И бонусом к этому не будут вызваны исключения при открытии файла (например, если файл не существует).

Чтение из файла

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

Работа со строками в Python. Готовимся к собеседованию: вспоминаем азы

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

with open("examp.le", "r") as f: text = f.read() 

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

with open("examp.le", "r") as f: part = f.read(16) 

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

with open("examp.le", "r") as f: # 'Hello, world!' first_part = f.read(8) # 'Hello, w' f.seek(4) second_part = f.read(8) # 'o, world' 

Другой способ заключается в считывании файла построчно. Метод readline() считывает строку и, также как и с методом read() , сдвигает курсор — только теперь уже на целую строку. Применение этого метода несколько раз будет приводить к считыванию нескольких строк. Схожий с этим способом, другой метод позволяет прочитать файл целиком, но по строкам, записав их в список. Этот список можно использовать, например, в качестве итерируемого объекта в цикле.

with open("examp.le", "r") as f: for line in f.readlines(): print(line) 

Однако и здесь существует более pythonic way. Он заключается в том, что сам объект io.TextIOWrapper имеет итератор, возвращающий строку за строкой. Благодаря этому нет необходимости считывать файл целиком, сохраняя его в список, а можно динамически по строкам считывать файл. И делать это лаконично.

with open("examp.le", "r") as f: for line in f: print(line) 

Запись в файл

Функциональность внесения данных в файл не зависит от режима — добавление данных или перезаписывание файла. В выполнении этой операции также существует несколько подходов.

Самый простой и логичный — использование функции write()

with open("examp.le", "w") as f: f.write(some_string_data) 

Важно, что в качестве аргумента функции могут быть переданы только строки. Если необходимо записать другого рода информацию, то ее необходимо явно привести к строковому типу, используя методы __str__(self) для объектов или форматированные строки.

Есть возможность записать в файл большой объем данных, если он может быть представлен в виде списка строк.

with open("examp.le", "w") as f: f.writelines(list_of_strings) 

Здесь есть еще один нюанс, связанный с тем, что функции write() и writelines() автоматически не ставят символ переноса строки, и это разработчику нужно контролировать самостоятельно.

Существует еще один, менее известный, способ, но, возможно, самый удобный из представленных. И как бы не было странно, он заключается в использовании функции print() . Сначала это утверждение может показаться странным, потому что общеизвестно, что с помощью нее происходит вывод в консоль. И это правда. Но если передать в необязательный аргумент file объект типа io.TextIOWrapper , каким и является объект файла, с которым мы работаем, то поток вывода функции print() перенаправляется из консоли в файл.

with open("examp.le", "w") as f: print(some_data, file=f) 

Сила такого подхода заключается в том, что в print() можно передавать не обязательно строковые аргументы — при необходимости функция сама их преобразует к строковому типу.

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

Следите за новыми постами по любимым темам

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

Лекция 5. Файлы в Си

Файл - это упорядоченная последовательность однотипных
компонентов, расположенных на внешнем носителе.
Файлы предназначены только для хранения информации, а
обработка этой информации осуществляется программами.
Использование файлов целесообразно в случае:
долговременного хранения данных;
доступа различных программ к одним и тем же данным;
обработки больших массивов данных, которые невозможно целиком разместить
в оперативной памяти компьютера.
Файл, не содержащий ни одного элемента, называется пустым.
Создается файл путем добавления новых записей в конец
первоначально пустого файла.
Длина файла, т.е. количество элементов, не задается при
определении файла.
В языке Си отсутствуют операторы для работы с файлами. Все
необходимые действия выполняются с помощью функций,
включенных в стандартную библиотеку ввода-вывода языка Си
(stdio.h - standart input output).

3. Буферизация ввода-вывода

Считываемая и записываемая информация представляет собой
последовательность байтов - "поток" (stream).
Поток – это логическое устройство, являющееся источником или
получателем данных.
В зависимости от того, откуда поступает считываемая информация или куда
направляется записываемая информация, поток связывается с соответствующим
устройством ввода вывода (клавиатура, дисплей, принтер и т.п.) или с
именованной областью внешней памяти – файлом, если требуется
долговременно хранить информацию либо получить доступ к хранимой
информации.
При организации ввода-вывода в С используется буферизация, то есть обмен
информацией между программой и внешним устройством происходит не
непосредственно, а через буфер – специально выделяемую системой область
оперативной памяти.
Буферизация ускоряет работу программы из-за уменьшения количества
обращений к внешним устройствам.
В библиотеке описана константа BUFSIZE, величина которой 512:
#define BUFSIZE
512
Для изменения размера буфера предназначены функции setbuf() или setvbuf().

4. Текстовый и бинарный режим работы с файлами

Библиотека stdio.h поддерживает текстовые и бинарные (двоичные)
потоки.
Текстовый поток – это последовательность строк, каждая из которых
заканчивается символом ‘\n’. Операционная среда может потребовать
коррекции текстового потока. Например, при вводе текстового потока
система преобразует символы возврат каретки 0x13 и перевод строки
0x10 в одиночный символ ‘\n’. При обнаружении в текстовом файле
символа с кодом 26 (0x26), т.е. признака конца файла, чтение файла в
текстовом режиме заканчивается, хотя файл может иметь
продолжение. При выводе текстового потока в среду операционной
системы происходит обратное преобразование.
Бинарный поток – это последовательность не преобразуемых байтов,
представляющих собой некоторые промежуточные данные, которые
обладают тем свойством, что если их записать, а затем прочесть той
же системой ввода-вывода, то будет получена информация,
совпадающая с исходной.

5. Функция fopen

Прежде чем читать или записывать информацию в файл, он должен быть открыт функцией
fopen и тем самым связан с потоком ввода-вывода. Функция открытия потока
возвращает указатель fp на предопределенную в библиотеке stdio.h структуру типа FILE
(содержащую всю необходимую для работы с потоком информацию) при успешном
открытии потока, или NULL в противном случае.
В stdio.h заданы 3 предопределенных потока :
stdin (стандартный поток ввода), stdout (стандартный поток
вывода), stderr (стандартный поток ошибок)
• Вывод данных через stdout и stderr по умолчанию осуществляется на консоль. Ввод
данных через stdin по умолчнию осуществляется через клавиатуру.
• Предопределенные потоки всегда открыты.
При открытии файла указатель на файл связывается с конкретным файлом на диске
(Если файл не может быть открыт по какой-либо причине, функция возвращает NULL. ) :
FILE *fp;
fp = fopen(“спецификация файла”, "способ использования файла");
“Спецификация файла” (т.е. имя файла и путь к нему) может, например, иметь вид:
"c:\\my_prog.txt" - для файла my_prog.txt на диске с: .
“Способ использования файла” - определяет режим открытия файла.

6. Режимы открытия файла.

r - открыть существующий файл для чтения;
w - создать новый файл для записи (если файл с указанным именем существует, то он
будет переписан);
а - дополнить файл (открыть существующий файл для записи информации, начиная с
конца файла, или создать файл, если он не существует);
r+ - открыть существующий файл для чтения и записи;
w+ - создать новый файл для чтения и записи;
a+ - дополнить или создать файл с возможностью чтения и записи;
rb - открыть двоичный файл для чтения;
wb - создать двоичный файл для записи;
аb - дополнить двоичный файл;
r+b - открыть двоичный файл для чтения и записи;
w+b - создать двоичный файл для чтения и записи;
а+b - дополнить двоичный файл с предоставлением возможности чтения и записи;
rt - открыть текстовой файл для чтения;
wt - создать текстовый файл для записи;
at - дополнить текстовый файл;
r+t - открыть текстовой файл для чтения и записи;
w+t - создать текстовый файл для чтения и записи;
a+t - дополнить текстовый файл с предоставлением возможности записи и чтения.
Строки вида r+b можно записывать и в другой форме: rb+.

7. Примеры открытия файлов

FILE *f_in, *f_out;
f_in = fopen ("My_file1","r");
f_out = fopen ("My_file2","w");

8. Функция fclose

После окончания работы с файлом он должен быть
закрыт. Закрытие файла (текстового или бинарного)
выполняется функцией fclose():
fclose(FILE *fp);
При этом разрывается связь указателя на
файл c внешним набором данных. Освободившийся
указатель можно использовать для другого файла.
При успешном завершении операции функция fclose( )
возвращает значение нуль. Любое другое значение
свидетельствует об ошибке.
Пример:
fclose(f_in);

9. Проверка признака конца файла

При каждой операции ввода/вывода происходит
перемещение указателя текущей позиции в файле,
в какой-то момент указатель достигает конца
файла. Структура типа FILE имеет поле – индикатор
конца файла. Функция feof() проверяет состояние
индикатора конца файла и возвращает значение 0,
если конец файла не был достигнут, или значение,
отличное от нуля, если был достигнут конец файла.
Функция имеет единственный аргумент –
указатель на поток типа FILE.
Вызов функции:
if (! feof(f_in))…
проверяет, что конец файла еще не достигнут.

10. Функции ввода/вывода. Функции fgetc() и fputc().

Функции ввода/вывода.
Функции fgetc() и fputc().
Простейший способ выполнить чтение из файла или
запись в файл – использовать функции getc() или putc().
Функция getc() выбирает из файла очередной символ; ей
нужно только знать указатель на файл:
char Symb = getc(f_in);
Если при обработке достигается конец файла, то
функция getc() возвращает значение EOF(end of file).
Функция putc() заносит значение символа Symb в файл, на
который указывает f_out. Формат вызова функции:
putc(Symb,f_out);

11. Функции fgetc() и fputc().

Функции fgetc() и fputc().
Пример 1. Текст из файла my_char.txt выводится на экран. Если файл не найден, на экран выводится
сообщение "File not found!":
#include
int main(void)
FILE *ptr;
unsigned char ch;
if ((ptr=fopen("my_char.txt","r"))!=NULL)
ch=fgetc(ptr);
while (!feof(ptr))
printf("%c",ch);
ch=fgetc(ptr);
>
fclose(ptr);
>
еlse printf("\nFile not found!");
return 0;
>
В этом примере для чтения из файла используется переменная ptr. При открытии файла производится проверка.
Если переменной ptr присвоено значение NULL, то файл не найден; на экран выводится соответствующее
сообщение, и программа завершается. Если ptr получила ненулевое значение, то файл открыт. Далее
выполняется чтение символов из файла до тех пор, пока не будет достигнут конец файла (!feof(ptr)).
Прочитанные символы помещаются в переменную ch, а затем выводятся на экран.

12. Функции getc() и putc().

Функции getc() и putc().
Пример 2. Записать в файл буквы, вводимые с клавиатуры.
Ввод продолжается до нажатия клавиши F6 или CTRL/z
(ввод символа EOF – конца файла):
#include
int main(void)
char c;
FILE *out;
out=fopen("Liter","w");
while ((c=getch( ) )!=EOF)
fputc(c,out);
fclose(out);
return 0;
>

13. Функции fscanf() и fprintf()

Функции fscanf() и fprintf()
Функции fscanf() и fprintf() выполняют форматированный ввод/вывод.
Чтение из файла выполняет функция fscanf():
fscanf(f_in,[строка формата],[список адресов переменных]);
Функция возвращает количество введенных значений или EOF.
Запись в файл осуществляет функция fprintf():
fprintf(f_out,[строка формата],[список переменных, констант]);
Функция возвращает количество выведенных байт (символов) или EOF.
Строка формата функций fscanf() и fprintf() формируется так же, как
при консольном вводе/выводе функциями printf() и scanf().
Следует заметить, что вызов функции
fscanf(stdin,[строка формата],[список адресов переменных]);
эквивалентен вызову
scanf([строка формата],[список адресов переменных]);
Аналогично,
fprintf(stdout, [строка формата],[список переменных, констант]);
эквивалентно
printf([строка формата],[список переменных, констант]);

14. Примеры программ, использующих функции fscanf() и fprintf().

Примеры программ, использующих
функции fscanf() и fprintf().
Пример 1. В программе создается массив, состоящий из четырех целых
чисел. Вывести массив в файл:
#include
#define n 4
int main() int i=0;
int array[n]=;
FILE *out;
out=fopen("num_arr.txt","w");
for(;i fprintf(out,"%6d",array[i]);
fclose(out);
return 0; >
В результате выполнения программы в файл num_arr.txt будет помещена
следующая информация:
4
4 4
4 4 6
4 4 6 6

15. Примеры программ, использующих функции fscanf() и fprintf().

Примеры программ, использующих
функции fscanf() и fprintf().
Пример 2. Имеется файл данных,
содержащий целые числа, разделенные
пробелами. Количество чисел в файле
неизвестно. Требуется найти среднее
арифметическое значение этих чисел.
#include
int main() int S=0, count=0, numb;
FILE *in;
if ((in=fopen("num_arr.txt","r"))!=NULL)
while (!feof(in))
fscanf(in,"%d",&numb);
S+=numb;
count++;
printf("%d\n", numb);
>
Чтение чисел из файла выполняется в
переменную numb до тех пор, пока не будет
достигнут конец файла. Одновременно
ведется подсчет количества прочитанных
символов в переменной count и накопление
double aver=(double)S/count;
суммы прочитанных чисел в переменной S.
printf("Average=%f\n", aver);
Переменные S и count целые, поэтому для
fclose(in);
правильного вычисления среднего
>
арифметического, необходимо выполнить
else
преобразование одной из этих переменных
printf("\nФайл не найден!");
в формат double.
return 0; >

16. Примеры программ, использующих функции fscanf() и fprintf().

Примеры программ, использующих
функции fscanf() и fprintf().
#include
#include
int main() int bal;
char name[15];
FILE *file;
if ((file = fopen("1.txt","w")) == NULL)
printf("Файл невозможно
открыть или создать\n");
else for(;;) scanf ("%d%s", &bal, name);
if (bal == 0)
break;
fprintf(file,"%d %s\n", bal,
name);
>
>
fclose(file);
return 0; >
Пример 3. Ввод имени и балла.
FILE *file;
объявляем указатель на структуру File ( дескриптор файла ).
if ((file = fopen("1.txt","w")) == NULL)
функция fopen принимает два параметра.
Первый - это имя файла,
второй - режим работы с файлом, в котором он будет открыт.
В нашем режиме, если файл не существует, то он создается,
а если файл уже был, то его содержимое полностью стирается.
Эта функция возвращает указатель на структуру FILE ,
т.е. теперь мы сможем управлять созданным файлом при
помощи нашего указателя file.
Оператор if тут используется, так как идет проверка
указателя на NULL, а NULL может быть, только если файл мы не
смогли открыть.
fprintf(file,"%d %s\n", bal, name);
оператор записывает данные в файл.
Принцип действия тот же, какой и у оператора printf, только тут
в начале указывается указатель на файл , в который будет
производится запись данных.
fclose(file);
раз данные мы записали и файл нам больше не нужен,
то смело может закрывать его, тем самым освобождая ресурсы.

17. Задание

Создайте 10 записей, содержащих
информацию о железнодорожных
маршрутах. В нём должны быть следующие
данные:
o номер пути
o номер вагона
o имя поезда
Запишите сами вручную эти данные в файл.
Затем вам необходимо считать эти данные и
вывести их на экран.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *