Примеры программ работы с файлами

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

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

Функция fputs() записывает в файл строку, то есть набор символов, который завершается символом ‘’. Она имеет следующий прототип:

int fputs(const char *s, FILE *stream);

Первый параметр функции — записываемая строка, а второй — указатель на файловый поток. В качестве результата функция возвращает неотрицательное целое число. При ошибках в процессе записи возвращается значение EOF .

При записи строки нулевой символ ‘’ в файл не записывается.

Например, запишем строку в файл:

#include int main(void) < // строка для записи char * message = «Hello METANIT.COM!nAn apple a day keeps the doctor away»; // файл для записи char * filename = «data.txt»; // запись в файл FILE *fp = fopen(filename, «w»); if(fp) < // записываем строку fputs(message, fp); fclose(fp); printf(«File has been writtenn»); >>

Запись довольно проста: открываем файл на запись и с помощью вызова fputs(message, fp) записываем в файл искомую строку.

Текстовые файлы в с++ | программа с использованием файлов

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

Функция fgets() считывает из файла одну строку и имеет следующий прототип:

char * fgets(char *s, int n, FILE *sream);

Первый параметр char *s представляет строку, в которую производится считывание. Второй параметр — число n указывает, сколько символов необходимо считывать. И третий параметр представляет файловый поток, из которого производится считывание.

При вызове функция считывает из файла не более n-1 символов. Функция прекращает чтение, когда прочтет n-1 символов или встретит символ переноса строки n. Все считанные символы записываются в строку s, в том числе символ n. И также конец каждой строки дописывается нулевой символ ‘’.

При успешном завершении функция возвращает указатель s , а при ошибке или достижении конца файла возвращается значение NULL .

Считаем данные из выше записанного файла «data.txt»:

#include int main(void) < // файл чтения char * filename = «data.txt»; // буфер для считавания данных из файла char buffer[256]; // чтение из файла FILE *fp = fopen(filename, «r»); if(fp) < // пока не дойдем до конца, считываем по 256 байт while((fgets(buffer, 256, fp))!=NULL) < printf(«%s», buffer); >fclose(fp); > >

Здеcь открываем файл на чтение и в цикле считываем из файла по 256 символов и выводим их на консоль с помощью вызова fgets(cc, 256, fp) . Когда данные в файле закончатся, функция возвратит NULL, и произойдет выход из цикла.

Копирование файлов

Другой пример работы с текстовыми файлами — копирование содержимого из одного файла в другой:

#include int main(void) < char * filename1 = «data1.txt»; char * filename2 = «data2.txt»; char buffer[256]; FILE *f1 = fopen(filename1, «r»); // файл на чтение FILE *f2 = fopen(filename2, «w»); // файл на запись if(!f1 || !f2) < printf(«Error occured while opening filen»); >else < // пока не дойдем до конца, считываем по 256 байт из файла f1 while((fgets(buffer, 256, f1))!=NULL) < // записываем строку в файл f2 fputs(buffer, f2); printf(«%s», buffer); >> fclose(f1); fclose(f2); return 0; >

Источник: metanit.com

Топ 5 bat-файлов которые вам пригодятся

4. Примеры программ работы с файлами

Обратите внимание на обработку параметров командной строки.

Фрагмент программы RW.C записи в файл / чтения из файла.

Программа воспринимает в качестве параметра командной

строки имя рабочего файла. Если файл не существует, он

будет создан, если существует, будет изменен

static int j = 1;

if (j > 10) return 0;

printf(«write %d — %dn», fd, j++);

printf(«read %d — %dn», fd, i);

void main(int argc, char *argv[])

Читайте также:
Как в программе 1с добавить Новую организацию

fd = open(argv[1], O_CREAT | O_RDWR);

Пример 2. Дублирование дескриптора файла.

Фрагмент программы DUP.C — перенаправление стандартного

int outf, std_out;

char *str1 = «Вывод строки в файл «,

*str2 = «Вывод строки на экран»;

/* закрытие стандартного вывода */

outf = open(«1.dat», O_WRONLY);

/* восстановление предыдущих значений */

outf = open(«devtty», O_WRONLY);

Лабораторная работа № 3. Процессы и сигналы ос unix

1. Теоретические сведения

1.1. Процессы ос unix

Работу ОС UNIX можно представить в виде функционирования множества взаимосвязанных процессов.

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

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

1.1.1. Выполнение процесса

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

С практической точки зрения процесс в системе UNIX является объектом, создаваемым в результате выполнения системного вызова fork. Каждый процесс, за исключением нулевого, порождается в результате запуска другим процессом операции fork. Процесс, запустивший операцию fork, называется родительским, а вновь созданный процесс — порожденным.

Каждый процесс имеет одного родителя, но может породить много процессов. Ядро системы идентифицирует каждый процесс по его номеру, который называется идентификатором процесса (PID). Нулевой процесс является особенным процессом, который создается «вручную» в результате загрузки системы. Процесс 1, известный под именем init, является предком любого другого процесса в системе и связан с каждым процессом.

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

  •  набора «заголовков», описывающих атрибуты файла;
  •  текста программы;
  •  представления на машинном языке данных, имеющих начальные значения при запуске программы на выполнение, и указания на то, сколько пространства памяти ядро системы выделит под неинициализированные данные, так называемые bss («block started by symbol» — «блок, начинающийся с символа»);
  •  других секций, таких как информация символических таблиц.

Ядро загружает исполняемый файл в память при выполнении системной операции exec, при этом загруженный процесс состоит по меньшей мере из трех частей, так называемых областей: текста, данных и стека. Области текста и данных соответствуют секциям текста и bss-данных исполняемого файла, а область стека создается автоматически и ее размер динамически устанавливается ядром системы во время выполнения. Процесс в системе UNIX может выполняться в двух режимах — режиме ядра или режиме задачи. В режиме задачи процесс выполняет инструкции прикладной программы, системные структуры данных ему недоступны. Когда процесс выполняет специальную инструкцию (системный вызов), он переключается в режим ядра. Каждой системной операции соответствует точка входа в библиотеке системных операций; библиотека системных операций написана на языке ассемблера и включает специальные команды прерывания, которые, выполняясь, порождают «прерывание», вызывающее переключение аппаратуры в режим ядра. Процесс ищет в библиотеке точку входа, соответствующую отдельной системной операции, подобно тому, как он вызывает любую из функций. Соответственно и образ процесса состоит из двух частей: данных режима ядра и режима задачи. В режиме ядра образ процесса включает сегменты кода, данных, библиотек и других структур, к которым он может получить непосредственный доступ. Образ процесса в режиме ядра состоит из структур данных, недоступных процессу в режиме задачи (например, состояния регистров, таблицы для отображения памяти и т.п.). Каждому процессу соответствует точка входа (запись) в таблице процессов ядра, кроме того, каждому процессу выделяется часть оперативной памяти, отведенной под задачи пользователей. Таблица процессов включает в себя указатели на промежуточную таблицу областей процессов, точки входа в которую служат в качестве указателей на собственно таблицу областей. Областью называется непрерывная зона адресного пространства, выделяемая процессу для размещения текста, данных и стека. Точки входа в таблицу областей описывают атрибуты области, как например, хранятся ли в области текст программы или данные, закрытая ли эта область или же совместно используемая, и где конкретно в памяти размещается содержимое области. Внешний уровень косвенной адресации (через промежуточную таблицу областей, используемых процессами, к собственно таблице областей) позволяет независимым процессам совместно использовать области. Когда процесс запускает системную операцию exec, ядро системы выделяет области под ее текст, данные и стек, освобождая старые области, которые использовались процессом. Если процесс запускает операцию fork, ядро удваивает размер адресного пространства старого процесса, позволяя процессам совместно использовать области, когда это возможно, и, с другой стороны, производя физическое копирование. Если процесс запускает операцию exit, ядро освобождает области, которые использовались процессом. На Рис.1 изображены информационные структуры, связанные с запуском процесса. Таблица процессов ссылается на промежуточную таблицу областей, используемых процессом, в которой содержатся указатели на записи в собственно таблице областей, соответствующие областям для текста, данных и стека процесса. Рисунок 1. Информационные структуры для процессов UNIX является системой разделения времени, это означает, что каждому процессу вычислительные ресурсы выделяются на ограниченный промежуток времени, после чего они предоставляются другому процессу. Максимальный временной интервал, на который процесс может захватить процессор, называется временным квантом. Таким образом, создается иллюзия того, что процессы работают одновременно, хотя в действительности на однопроцессорной машине одновременно может выполняться только один процесс. Процессы предъявляют различные требования к системе с точки зрения их планирования и общей производительности. Можно выделить три основных класса приложений:

  • интерактивные приложения (командные интерпретаторы, редакторы и проч.). Большую часть времени они проводят в ожидании пользовательского ввода, но для них критично время отклика (реакции системы на ввод данных).
  • фоновые приложения (не требующие вмешательства пользователя). Основной показатель эффективности для них — минимальное суммарное время выполнения в системе.
  • приложения реального времени. Они обычно привязаны к таймеру и требуют гарантированного времени совершения той или иной операции и времени отклика.
Читайте также:
Как нарисовать домик в программе чертежник

В основе планирования выполнения процессов лежат два понятия: квант времени и приоритет. Каждый процесс имеет два атрибута приоритета: текущий (на основании которого осуществляется планирование) и относительный, который задается при порождении процесса и влияет на текущий. Номера приоритетов разбиваются на несколько групп: для процессов в режиме задачи, в режиме ядра, для процессов реального времени (группы указаны в соответствии с повышением приоритета). Обработчик прерываний от таймера, в частности, проверяет истечение временного кванта для процессов и пересчитывает приоритеты процессов: чем дольше процесс занимает процессор, тем ниже (в пределах группы) становится его приоритет. Выполнение процесса может быть прервано: а) планировщиком процессов по истечении временного кванта или в том случае, если в очереди готовых к исполнению процессов есть процесс с более высоким приоритетом. б) ядром системы, если процесс ожидает недоступного ресурса или окончания длительной операции ввода/вывода. В режиме ядра приоритет процесса повышается для того, чтобы его выполнение не могло быть прервано, так как это может привести к нарушению целостности структур данных ядра. Таким образом, выполнение системных вызовов осуществляется в непрерывном режиме (за исключением некоторых аппаратных прерываний).

Источник: studfile.net

Работа с файлами в C++ с использованием Boost

Привет! Я время от времени рассказываю на Хабре о решениях распространённых задач на C++ и вообще люблю делиться опытом. Поэтому даже написал целую книгу, которая называется «Разработка приложений на С++ с использованием Boost».

Она может быть интересна разработчикам, которые уже немного знакомы со стандартной библиотекой языка, хотят глубже изучить Boost, упростить и повысить качество разработки приложений. Уверен, что информация, которую я собрал в книге, будет полезна — всё больше библиотек Boost становятся частью стандарта. Сегодня предлагаю прочитать главу, посвящённую работе с файлами.

Читайте также:
Селекс программа для зоотехников это

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

UPD: добавил в конец поста бонус для читателей Хабра.

Перечисление файлов в каталоге

Существуют функции и классы стандартной библиотеки для чтения и записи данных в файлы. Но до появления C++17 в ней не было функций для вывода списка файлов в каталоге, получения типа файла или получения прав доступа к файлу.

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

Знание основ C++ более чем достаточно для использования этого рецепта. Этот рецепт требует линковки с библиотеками boost_system и boost_filesystem.

Как это делается.

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

    Нам нужно подключить следующие два заголовочных файла:

#include #include
int main() < boost::filesystem::directory_iterator begin(«./»);
boost::filesystem::directory_iterator end; for (; begin != end; ++ begin)
boost::filesystem::file_status fs = boost::filesystem::status(*begin);
switch (fs.type()) < case boost::filesystem::regular_file: std::cout if (fs.permissions() std::cout else
std::cout /*for*/ > /*main*/

FILE W «./main.o»
FILE W «./listing_files»
DIRECTORY W «./some_directory»
FILE W «./Makefile»

Как это работает.

Функции и классы Boost.Filesystem просто оборачивают системные вызовы для работы с файлами.

Обратите внимание на использование знака «./» на этапе 2. Системы POSIX используют косую черту для указания путей; Windows по умолчанию использует обратную косую черту. Тем не менее Windows также понимает косую черту, а даже если бы не понимала, то библиотека Boost позаботилась бы о неявном преобразовании формата пути.

Посмотрите на этап 3, где мы вызываем конструктор по умолчанию для класса boost::filesystem::directory_iterator. Этот конструктор работает по аналогии с конструктором по умолчанию класса std::istream_iterator, – создает итератор конца диапазона.

Этап 4 сложен не потому, что эту функцию трудно понять, а из-за того, что происходит много преобразований. Разыменование итератора begin возвращает boost::filesystem::directory_entry, который неявно преобразуется в boost::filesystem::path, использующийся в качестве параметра для функции boost::filesystem::status. На самом деле можно написать намного лучше:

boost::filesystem::file_status fs = begin->status();

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

Этап 5 очевиден, поэтому мы переходим к этапу 6, где неявное преобразование в boost::filesystem::path происходит снова. Более явное решение выглядит так:

std::cout path()

Здесь begin->path() возвращает константную ссылку на переменную
boost::filesystem::path, которая содержится в boost::filesystem::directory_entry.

Дополнительно.

Boost.Filesystem является частью C++17. Все содержимое в C++17 находится в одном заголовочном файле в пространстве имен std::filesystem. Версия стандартной библиотеки несколько отличается от Boost-версии, в основном за счет использования перечислений с областью видимости (enum class) там, где Boost.Filesystem использовала просто перечисление без области видимости.

Совет:
Есть класс directory_entry, который обеспечивает кеширование информации о файловой системе. Так что если вы много работаете с файловой системой и запрашиваете различную информацию, попробуйте использовать directory_entry для лучшей производительности.

Как и в случае с другими библиотеками Boost, Boost.Filesystem работает с компиляторами для стандарта, предшествующего C++17, и даже с компиляторами для стандарта, предшествующего C++11.

См. также

Стирание и создание файлов и каталогов

Давайте рассмотрим следующие строки кода:

std::ofstream ofs(«dir/subdir/file.txt»); ofs

В этих строках мы пытаемся записать что-то в файл file.txt в каталоге dir/ subdir. Если такой директории нет, эта попытка будет неудачной.

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

Давайте посмотрим, как можно сделать это элегантно, используя Boost.

Подготовка

Для этого рецепта требуются базовые знания C++ и класса std::ofstream.

Boost.Filesystem не является библиотекой header-only, поэтому код в этом ре-
цепте требуется линковать с библиотеками boost_system и boost_filesystem.

Как это делается.

Рейтинг
( Пока оценок нет )
Загрузка ...
EFT-Soft.ru