Студопедия.Орг Главная | Случайная страница | Контакты | Мы поможем в написании вашей работы!  
 

Закриття файлу



Для закриття файлу використовується функція-член| close(). Наприклад, щоб закрити файл, пов'язаний з потоком mystream, необхідна наступна інструкція:

mystream.close ();

Функція close() не має аргументів і не повертає значення.

9.4.3 Функція eof()

За допомогою функції eof(), що є членом класу ios, можна визначити, чи був досягнутий кінець файлу вводу. Нижче представлений прототип цієї функції:

bool eof();

Функція повертає істину, якщо був досягнутий кінець файлу; інакше функціяповертає неправду.

9.4.4 Операції читання і запису для файлів

Після того, як файл відкритий, дуже легко прочитати з нього або записати в нього текстові дані. Просто потрібно використати оператори << та >> так само, як це робиться для консольного вводу – виводу; тільки потік cin або cout замінюється тим потоком, який пов'язаний з файлом.

Так само, як і оператори << та >>, для читання з файлу і запису у файл годяться функції C — fprintf() і fscanf(). Вся інформація у файлі зберігається в тому ж форматі, неначебто вона знаходиться на екрані. Отже, файл, створений за допомогою оператора <<, є файлом з відформатованим текстом. І навпаки, будь-який файл, вміст якого прочитується за допомогою оператора >>, повинен бути файлом з відформатованим текстом.

У представленій нижче програмі створюється файл для виводу, в нього записується інформація, і файл закривається. Потім файл знову відкривається вже як файл для вводу, і записана раніше інформація звідти прочитується:

#include <iostream>

#include <fstream>

using namespace std;

int main()

{

ofstream fout("test"); // створення файлу для виводу

if(!fout)

{

cout << "Файл відкрити неможливо \n";

return 1;

}

fout << "Привіт!\n";

fout << 100 << ' ' << hex << 100 << endl;

fout.close ();

ifstream fin("test"); // відкриття файлу для вводу

if(!fin)

{

cout << "Файл відкрити неможливо \n";

return 1;

}

char str[80];

int i;

fin >> str >> i;

cout << str << ' ' << i << endl;

fin.close ();

return 0;

}

Після роботи програми на диску залишиться файл з ім'ям "test", який міститиме інформацію, яка відформатована так, як якби вона видавалася на екран:

Привіт!

100 64

9.5 Двійковий неформатний ввід - вивід

Хоча текстові файли корисні в багатьох ситуаціях, у них немає гнучкості неформатних двійкових файлів. Неформатовані файли містять ті самі початкові або "сирі" двійкові дані, які безпосередньо використовуються програмою, а не зручний для сприйняття людиною текст, дані якого заради легкості для читання перетворюються операторами << та >>. Тому про неформатний ввід - вивід іноді говорять як про "сирий" (row) ввід - вивід.

В C++ для двійкових файлів підтримується широкий діапазон функцій вводу - виводу. Ці функції дають можливість точно контролювати процеси читання з файлів і запису до файлів.

9.5.1 Основні| функції двійкового вводу - виводу

На нижньому рівні двійкового вводу - виводу знаходяться функції get() і put(). За допомогою функції-члена put() можна записати байт, а за допомогою функції-члена get() — прочитати. Ці функції є членами всіх потокових класів відповідно для вводу і для виводу. Функції get() і put() мають багато форматів. Нижче представлені їх варіанти, що найбільш часто зустрічаються в програмах:

istream &get (char &ch);

ostream &put(char ch);

Функція get() прочитує один символ з пов'язаного з нею потоку і передає його значення аргументу ch. Значенням, що вона повертає, є посилання на потік. При прочитуванні символу кінця файла функціяповерне викликаючому потоку значення false. Функція put() записує символ ch у потік і повертає посилання на потік.

Для прочитування і запису блоків двійкових даних використовуються функції read() і write(), які також є членами потокових класів для вводу і для виводу, відповідно. Нижче приведені їх прототипи:

istream &read(char *buffer, streamsize size);

ostream &write (const char *buffer, streamsize size);

Функція read() прочитує із викликаючого потоку стільки байтів, скільки задано в аргументі size і передає їх в буфер, визначений вказівником buffer. Функція write() записує у відповідний потік з буфера, який визначений вказівником buffer, задане в аргументі size число байтів. Тип streamsize є різновидом цілого.

Якщо кінець файлу досягнутий до того, як було прочитано size символів, виконання функції read() просто припиняється, а в буфері буде знаходитись стільки символів, скільки їх було у файлі. Дізнатися, скільки символів було прочитано, можна за допомогою іншої функції-члена gcount(), прототип якої приведений нижче:

streamsize gcount();

Ця функціяповертає кількість символів, прочитаних під час останньої операції двійкового вводу.

Природно, що при використанні функцій, призначених для роботи з двійковими файлами, файли повинні відкриватися в двійковому, а не в текстовому режимі. Значення режиму відкриття файлу ios::binary запобігає якому б то не було перетворенню символів. Це важливо, коли у файлі зберігаються двійкові дані, наприклад, цілі, дійсні числа або вказівники.

Проте для файлу, відкритого в текстовому режимі, хоча в ньому міститься тільки текст, двійкові функції цілком доступні; при цьому потрібно пам'ятати про можливість небажаного приведення символів.

В наступній програмі спочатку масив чисел з плаваючою крапкою подвійної точності записується у файл, а потім прочитується назад. За допомогою функції gcount() відображається число прочитаних символів:

#include <iostream>

#include <fstream>

using namespace std;

int main()

{

ofstream out("test", ios::out | ios::binary);

if(!out)

{

cout << "Не можна відкрити файл для виводу. \n";

return 1;

}

double nums[4]= {1.1, 2.2, 3.3, 4.4 };

out.write((char *) nums, sizeof(nums));

out.close();

ifstream in("test", ios::in | ios::binary);

if(!in)

{

cout << "Не можна відкрити файл для вводу. \n";

return 1;

}

in.read((char *) &nums, sizeof(nums));

int i;

for(i=0; i<4; i++)

cout << nums[i]<< ' ';

cout << '\n';

cout << in.gcount() << " символів прочитано. \n";

in.close();

return 0;

}

9.5.2 Додаткові функції двійкового вводу - виводу

Окрім представленого раніше варіанту, функцію get() можна перевантажувати ще декількома способами. Нижче приведені прототипи трьох найчастіше використовуваних форматів цієї функції:

istream& get(char *buffer, streamsize size);

istream& get(char *buffer, streamsize size, char d);

int get();

Перша функціяget() прочитує символи в буфер, заданий вказівником buffer, до тих пір, поки або буде прочитано стільки символів, скільки задано аргументом size - 1, або не зустрінеться символ кінця файлу. В кінці буфера, заданого вказівником buffer, функція get() поміщає нуль. Якщо в потоці вводу зустрівся символ нового рядка, він не вибирається з потоку, а залишається в потоці до наступної операції вводу.

Друга функціяget() прочитує символи в буфер, заданий вказівником buffer, до тих пір, поки або буде прочитано стільки символів, скільки задано аргументом size - 1, або не зустрінеться символ, заданий аргументом d (символ – обмежувач), або не зустрінеться символ кінця файлу. В кінець буфера, заданого вказівником buffer, функція get() поміщає нуль. Якщо в потоці вводу зустрінеться символ - обмежувач, він не вибирається, а залишається в потоці до наступної операції вводу.

Третя функціяget() вибирає з потоку черговий символ. Вона повертає символ EOF, якщо буде досягнутий кінець файлу. Ця форма get() нагадує функцію getc() мови С.

Іншою функцією для реалізації вводу є функціяgetline(). Ця функція є членом всіх потокових класів вводу. Нижче приведені її прототипи:

istream& getline(char *buffer, streamsize size);

istream& getline(char *buffer, streamsize size, char d);

Перша функціяgetline() прочитує символи в буфер, заданий вказівником buffer, до тих пір, поки або буде прочитано стільки символів, скільки задано аргументом size - 1, або не зустрінеться символ нового рядка, або символ кінця файлу. В кінці буфера, заданого вказівником buffer, функція getline() поміщає нуль. Якщо в потоці вводу зустрінеться символ нового рядка, він вибирається з потоку, але не поміщається в буфер.

Друга функціяgetline() прочитує символи в буфер, заданий вказівником buffer, до тих пір, поки або буде прочитано стільки символів, скільки задано аргументом size - 1, або не зустрінеться символ, заданий аргументом d (символ – обмежувач рядка), або не зустрінеться символ кінця файлу. В кінець буфера, заданого вказівником buffer, функція getline() поміщає нуль. Якщо в потоці вводу зустрінеться символ – обмежувач рядка d, він вибирається, але не поміщається в буфер.

Як можна помітити, обидві версії функції getline() фактично тотожні варіантам функції get() з відповідними аргументами. Обидві прочитують символи з потоку вводу і поміщають їх в буфер, заданий вказівником buffer, до тих пір, поки або не прочитано size - 1 символів, або не зустрівся символ – обмежувач, або символ кінця файлу. Відмінність між функціями get() і getline() у тому, що функціяgetline() прочитує і видаляє з потоку вводу символ - обмежувач, а функція get() - ні.

Використовуючи функцію peek(), можна одержати наступний символ з потоку вводу без його видалення з потоку. Функція є членом потокових класів вводу і має наступний прототип:

int peek();

Функція повертає наступний символ з потоку або, якщо був досягнутий кінець файлу, символ EOF.

За допомогою функції putback(), що є членом потокових класів вводу, можна повернути останній прочитаний з потоку символ назад в потік. Нижче приведений прототип цієї функції:

ifstream putback(char c);

Тут c - це останній прочитаний з потоку символ.

При виконанні виводу дані не відразу записуються на пов'язаний з потоком фізичний пристрій, а інформація тимчасово зберігається у внутрішньому буфері. Тільки після заповнення буфера його вміст передається на носій. Проте виклик функції flush() викликає фізичний запис інформації на носій до заповнення буфера. Нижче показаний прототип
функції flush(), що є членом потокових класів виводу:

ostream &flush();

Виклики функції flush() виправдані при роботі у несприятливій обстановці, наприклад, в ситуаціях, коли часто трапляються збої по живленню.

Нижче наводиться приклад програми, що використовує функції peek() і putback(), оскільки вони особливо корисні в реальному програмуванні. Ці функції дозволяють спростити управління, коли невідомий тип інформації, що вводиться в кожен конкретний момент часу. У програмі з файлу прочитуються цілі числа або рядки символів. Рядки й цілі можуть слідувати в будь-якому порядку:

#include <iostream>

#include <fstream>

#include <cctype>

using namespace std;

int main()

{

char ch;

ofstream out("test", ios::out | ios::binary);

if(!out)

{

cout << "Не можна відкрити файл для виводу. \n";

return 1;

}

char str[80] *p;

out << 123 << "this is а test" << 23;

out << "Hello there!" << 99 << "sdf" << endl;

out.close();

ifstream in("test", ios::in | ios::binary);

if(!in)

{

cout << " Не можна відкрити файл для вводу. \n";

return 1;

}

do

{

p = str;

ch = in.peek();

if(isdigit(ch)) // визначення типу чергового символу

{

while(isdigit(*p=in.get())) p++; // читання цілого

in.putback(*p); // повернення символу в потік

*p = '\0'; // закінчуємо рядок нулем

cout << "Ціле: " << atoi(str);

}

else if(isalpha(ch))

{

while(isalpha(*p=in.get())) p++; // читання рядка

in.putback(*p); // повернення символу в потік

*p = '\0'; // закінчуємо рядок нулем

cout << "Рядок: " << str;

}

else

in.get(); // пропуск

cout << '\n';

} while(!in.eof());

in.close();

return 0;

}

9.6 Довільний доступ

У системі вводу – виводу мови C++ довільний доступ (random access) реалізується за допомогою функцій seekg() і seekp(), що є потоковими функціями відповідно вводу і виводу. Нижче приводяться їх основні| прототипи:

istream& seekg(off_type disp, seekdir dir);

ostream& seekp(off_type disp, seekdir dir);

Тут off_type — це цілий тип даних, оголошений в класі ios і сумісний з максимальним правильним значенням, яке здатний зберігати аргумент віддалення у файлі disp. Тип seekdir — це перелік, що оголошений в класі ios і містить наступні значення:

ios::beg – віддалення від початку файлу;

ios::cur – віддалення від поточної позиції у файлі;

ios::end - віддалення від кінця файлу.

Система вводу - виводу C++ управляє двома вказівниками, пов'язаними з файлом. Перший — це вказівник зчитування (get pointer), який задає наступне місце у файлі, звідки буде вводитися інформація. Другий - це вказівник запису (put pointer), який задає наступне місце у файлі, куди буде виводитися інформація. При кожному вводі або виводі відповідний вказівник послідовно просувається далі. Проте за допомогою функцій seekg() і seekp() можливий непослідовний доступ до файлу.

Функція seekg() встановлює вказівник зчитування відповідного файлу в позицію, що відстоїть| на величину віддалення disp від заданого місця dir. Функція seekp() встановлює вказівник запису відповідного файлу в позицію, що відстоїть| на величину віддалення disp від заданого місця dir.

Як правило, файли, доступні для функцій seekg() і seekp(), повинні відкриватися в режимі операцій для двійкових файлів. За допомогою цього режиму виключається можливе несподіване перетворення символів усередині файлу.

Визначити поточну позицію кожного з двох вказівників можна за допомогою функцій:

pos_type tellg();

pos_type tellp();

У прототипах pos_type - це цілий тип даних, оголошений в класі ios і здатний зберігати найбільше можливе значення вказівника.

Для переміщення файлових вказівників зчитування і запису на позицію, задану значеннями, що повертають функції tellg() і tellp(), використовуються перевантажені версії функцій seekg() і seekp(), прототипи яких представлені нижче:

istream& seekg (pos_type pos);

ostream& seekp(pos_type pos);

У наступній демонстраційній програмі функціяseekg() використовується для установки вказівника зчитування в задану позицію всередині файлу і для виводу вмісту файлу, починаючи з цієї позиції. Ім'я файлу і позиція зчитування задаються в командному рядку:

#include <iostream>

#include <fstream>

#include <cstdlib>

using namespace std;

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

{

char ch;

if(argc!=3)

{

cout << "Пошук: <файл> <позиція> \n";

return 1;

}

ifstream in(argv[1], ios::in | ios::binary);

if(!in)

{

cout << "Файл відкрити неможливо. \n";

return 1;

}

in.seekg(atoi(argv[2]), ios::beg);

while(!in.eof())

{

in.get(ch);

cout << ch;

}

in.close();

return 0;

}





Дата публикования: 2014-11-03; Прочитано: 1321 | Нарушение авторского права страницы | Мы поможем в написании вашей работы!



studopedia.org - Студопедия.Орг - 2014-2024 год. Студопедия не является автором материалов, которые размещены. Но предоставляет возможность бесплатного использования (0.021 с)...