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



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

Метод Описание
open Открывает файл для записи
put Записывает одиночный символ в файл
write Записывает заданное число байт из памяти в файл
seekp Перемещает указатель позиционирования в указанное положение
tellp Возвращает текущее значение указателя позиционирования файла
close Закрывает файл

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

ofstream file ("temp.txt");

if (!file) return;

for (int i=1; i<=3; i++)

file << "Строка " << i << endl;

file.close();

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

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

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

#include <iostream>

#include <fstream>

#include <locale>

using namespace std;

struct Notes { // структура данных записной книжки

 char Name[60]; // Ф.И.О.

 char Phone[16]; // телефон

 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[80];                    // статический буфер строки

 // Считывать и отображать строки в цикле, пока не 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 <iostream>

#include <fstream>

#include <locale>

using namespace std;

struct Notes { char Name[60]; char Phone[16]; 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[80];

 // Считывать и отображать записи в цикле, пока не 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 поменяются местами.

По аналогии с предыдущими примерами напишите программный код (исходные файлы задаются самостоятельно).

ВАРИАНТ:

0. определения чаще всего встречающейся в заданном файле буквы;

1. удвоения в содержимом файла каждой литеры(символа);

2. подсчёта числа цифр в данном файле и их суммы;

3. подсчета количества слов в файле (отделяются пробелами);

4. подсчитать количество строк в файле

5. в выходной файл записать исходный без разбивки по строкам

6. разбить входной файл(состоящий из одной строки не более 256 символов) на файл, содержащий информацию из входного, разбитого на строки, каждая размером соответствующая числу, вводимому с клавиатуры;

7. подсчитать в исходном файле количество цифр и символов. В выходной файл записать те данные, количество которых больше.

8. записать в выходной файл данные из исходного без символов, которые будут указаны при вводе с клавиатуры(может быть несколько но не более 5)

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

 

Покажите выполненную работу преподавателю.

 


Дата добавления: 2021-04-15; просмотров: 210; Мы поможем в написании вашей работы!

Поделиться с друзьями:






Мы поможем в написании ваших работ!