68972

Файли. Робота з файлами. Файловий ввід-вивід

Лекция

Информатика, кибернетика и программирование

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

Украинкский

2014-09-28

58 KB

4 чел.

Лекція № 17

Тема: Файли. Робота з файлами.

План

  1.  Файловий ввід-вивід
  2.  Відкриття і закриття потоку
  3.  Читання і запис текстових файлів
  4.  Безформатне і бінарне введення-виведення

Файловий ввід-вивід

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

Для реалізації файлового введення-виведення в програму слід включити заголовок <fstream>. У нім визначені деякі класи, зокрема, ifstream, ofstream і f stream. Ці класи є похідними від класів istream, ostream і ios-tream відповідно. Слід пам'ятати, що класи istream, ostream і iostream, у свою чергу, є похідними від класу ios, розглянутого в попередньому розділі. Файлова система використовує також клас filebuf, що надає низкоуровневые засоби управління файловим потоком. Зазвичай клас filebuf непосредственно не застосовується, проте він є складовою частиною інших класів.

 

Відкриття і закриття файлу

У мові C++ відкриття файлу означає його пов'язання з потоком. Отже, спочатку необхідно отримати потік. Існують три види потоків: введення, виведення і введення-виведення. Для того, щоб створити потік введення, необхідно оголосити потік, що є об'єктом класу ifstream Для генерації потоку виведення необхідно оголосити потік, що є об'єктом класу ofstream. Потоки, здійснююче введення і виведення, оголошуються як об'єкти класу fstream Наприклад, в наступному фрагменті створюється потік введення, потік виведення і потік введення-виведення.

ifstream in;  // Введення

ofstream out; // Виведення

fstream io;   // Введення і виведення

Створений потік можна пов'язати з файлом за допомогою функції ореn(). Ця функція є членом кожного з трьох потокових класів. Її прототипи в кожному класі показані нижче.

ifstream::open(const char *filename, ios::openmode

mode = ios::in);

ifstream: : open (const char  * filename,   

ios : : openmode mode = ios::out | ios::trunc);

ifstream::open(const  char  * filename,   

ios::openmode mode = ios::in   |   ios::out);

Тут параметр filename задає ім'я файлу. Він може містити шлях до цього файлу. Значення параметра mode визначає спосіб відкриття файлу. Цей параметр може приймати наступні значення, описані у функції openmode.

ios::арр ios::ate ios::binary ios::in ios::out ios::trunc

Дані значення можна комбінувати за допомогою логічної операції "АБО". Якщо задається значення ios:: арр, всі результати дописуються в кінець файлу, що риється для виведення. Якщо вказано значення ios: :ate, при відкритті виконується позов кінця файлу. Не дивлячись на це, запис проводиться в будь-яке місце файлу. Якщо задається значення ios:: in, файл відкривається для введення, а якщо ios:: out —  виведення.

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

Значення ios::trunc сигналізує, що попередній вміст існуючого файлу з тим же ім'ям буде знищений, а довжина файлу зменшена до нуля. При відкритті потоку виведення за допомогою класу ofstream вміст будь-якого існуючого файлу з вказаним ім'ям стирається. В наступному фрагменті відкривається текстовий файл для виведення.

 

ofstream out; out.open( "test", ios::out);

 

Проте функція open() рідко застосовується для відкриття файлів, оскільки для кожного типу потоку параметр mode має значення, задані за умовчанням. Прототипи функції open демонструють, що значення параметра mode, задане по замовчуванню, в класі ifstream рівне ios::in, в класі ofstream – ios::out | ios: :trunc, а в класі fstream — ios: :in | ios: :out. По цій причині попередній виклик функції open зазвичай записують так:

out.open(" test"); // Текстовий файл для виведення

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

if(!mystream)   {

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

// Обробка помилки

}

Однак частіше за все функцію ореn() не застосовують, оскільки класи ifstream, ofstream і fstream містять конструктори, що автоматично відкривають файл. Параметри цих конструкторів приймають ті ж значення за умовчанням, що і функція ореn(). З цієї причини файли зазвичай відкривають таким чином.

ifstream mystream( "myfile");   //  Відкриття файлу для  введення

Якщо з якої-небудь причини файл відкрити не вдалося, пов'язаному з ним потоку присвоюється значення false. Отже, якщо якийсь конструктор викликає функцію open(), слід переконатися, що файл дійсно відкритий, перевіривши значення потоку.

Щоб перевірити, чи відкритий файл, можна викликати функцію is_open(), яка є членом класу fstream, ifstream і ofstream. Вона має наступний прототип.

bool is_open();

Якщо потік пов'язаний з відкритим файлом, ця функція повертає значення true, інакше вона повертає значення false. Наприклад, наступний фрагмент перевіряє, чи відкритий файл, пов'язаний з потоком mystream.

if(!mystream.is_open())  {

cout «   "Файл не  відкритий.\n";

//   ...

}

Щоб закрити файл, слід викликати функцію close(). Наприклад, щоб закрити файл, пов'язаний з потоком mystream, можна застосувати наступний оператор

mystream.close() ;

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

Читання і запис текстових файлів

Читання і запис текстових файлів здійснюються дуже легко. Для цього достатньо застосувати операторів "<<" і ">>", як це зазвичай робиться для консольного введення-виведення, тільки замість потоків cin і cout необхідно підставити потік, що зв’язаний з файлом. Наприклад, наступна програма створює короткий файл, який містить назву предмету і його вартість.

#include <iostream>

#include <fstream>

using namespace std;

int main() {

ofstream out("INVNTRY"); // Текстовий файл для виведення.

if(!out){

cout « "Неможливо відкрити файл INVENTORY.\n";

return 1;

}

out << "Радіоприймачі " « 39.95 « endl;

out « "Тостери " « 19.95 « endl;

out « "Міксери " « 24.80 « endl;

out.close();

return 0;

}

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

#include <iostream>

#include <fstream>

using namespace std;

int main () {

ifstream in("INVNTRY");   //  Введення

if(!in)  {

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

return  1;

}

char item[20];

float cost;

in »  item »    cost;

cout «  item «   "   "  «  cost «   "\n"

in » item >> cost;

cout «  item «   "   "   «  cost «   "\n"

in >> item » cost;

cout «  item «   "   "   « cost «   "\n"

in.close() ;

return 0;

}

 

Читання і запис файлів за допомогою операторів "«" і "»" нагадує використання функцій fprintf() і fscanf() з мови С. Формат записів у файлі нічим не відрізняється від формату виведення на екран.

Прочитуючи файли за допомогою оператора ">>", майте на увазі, що деякі символи при введенні трансформуються. Наприклад, роздільники ігноруються. Щоб відмінити перетворення символів при читанні, файл слід відкрити в бинарному режимі і застосувати функції, описані в наступному розділі.

Якщо при введенні досягається кінець файлу, потоку, пов'язаному з файлом, присвоюється значення false. (Ця ситуація ілюструється в наступному розділі.)

 

Безформатне і бінарне уведення-виведення

Отже, читання і запис форматованих текстових файлів не викликає ніяких труднощів, хоча це не найефективніший спосіб роботи з файлами. Окрім цього іноді виникає необхідність зберігати безформатні дані, а не текст. Розглянемо функції, призначені для роботи з такими даними.

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

Порівняння символів і байтів

При вивченні безформатного введення-виведення необхідно враховувати наступне. Багато років уведення-виведення в мовах С і C++ був байтовим (byte oriented). Це відбувалося тому, що символ (char) є еквівалентом байта, і потоки виведення були символьними. Проте з появою розширених символів (wchar_t і пов'язаних з ними потоків систему введення-виведення мови C++ не можна назвати байтовою. Тепер її слід називати символьною (character oriented). Зрозуміло, потоки звичайних символів (char) залишаються байтовими, особливо при обробці нетекстових даних. Проте еквівалентність понять "символ" і "байт" більше не гарантуєте

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

Функції put() і get()

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

Функція get () має декілька форм, проте найчастіше використовується її наступна версія.

istream &get(char &ch)

ostream &put(char ch)

Функція get () прочитує окремий символ з потоку і записує його в змінну ch. Крім того, функція get () повертає посилання на потік. Функція put() записує змінну ch в потік і повертає посилання на потік

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

#include <iostream>

#include <fstream>

using namespace  std;

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

{

char  ch;

if(argc!=2){

cout << "виклик: PR <ім'я файла>\n";

return 1;

}

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

if(!in){

cout « "Неможливо відкрити файл.";

return 1;

}

while(in)  {   //  Якщо досягнутий кінець файлу

//  значення  об'єкту  in рівне  false.

in.get(ch);

if(in)  cout  «   ch;

}

return 0;

}

Як указувалося в попередньому розділі, після досягнення кінця файлу потік, связанный з цим файлом, приймає значення false. Отже, рано чи пізно об'єкт in прийме значення false, і виконання циклу while припиниться.

Приведений вище цикл можна записати коротше.

while(in.get(ch)) cout «  ch;

Цей фрагмент є правильним, оскільки функція get () повертає ссылку на потік in, який прийме значення false при виявленні кінця файлу.

Функції read() і write()

Блоки бінарних даних можна прочитувати за допомогою функцій read() i  write(). Їх прототипи виглядають таким чином.

istream &read(char  *buf,   streamsize num);

istream &write(const char  *buf,   streamsize num);

Функція read прочитує num символів з потоку і записує їх в буфер, на який посилається покажчик buf. Функція write записує num символів в потік прочитуючи їх з буфера, на який посилається покажчик buf. Тип streamsize визначений в бібліотеці як різновид типу int. Він дозволяє зберігати максимальну кількість символів, які можуть перетворюватися при виконанні операцій введення-виведення.


 

А также другие работы, которые могут Вас заинтересовать

8707. Методика організації самостійної роботи майбутніх інженерів-педагогів при викладанні дисципліни Деталі машин (на прикладі Української інженерно-педагогічної академії) 1.49 MB
  РЕФЕРАТ Мета дослідження: Теоретично обґрунтувати та розробити методику організації самостійної роботи майбутніх інженерів-педагогів при вивченні дисципліни Деталі машин (на прикладі Української інженерно-педагогічної академії)...
8708. Путешествие в Компьютерную Долину 1.31 MB
  УРОК ИНФОРМАТИКИ Путешествие в Компьютерную Долину Класс: 4 Учитель: Батура Полина Николаевна Учитель информатики и математики Казенное образовательное учреждение Тарская средняя общеобразовательная школа №3 Тип: игра, обобщение мате...
8709. Структура вимірювально-керуючої системи на основі комп’ютера 147 KB
  Структура вимірювально-керуючої системи на основі компютера План 1.1. Будова і призначення вимірювально-керуючої системи 1.2. Біологічні та технічні системи 1.3. Концепція побудови віртуального вимірювального комплексу 1.4. Програмна та ...
8710. Вимірювальні перетворювачі (сенсори, датчики) 172.5 KB
  Вимірювальні перетворювачі(сенсори, датчики) План. Характеристики (параметри) датчиків. Статичні характеристики датчиків. Динамічні характеристики датчиків. Сфери застосування датчиків. Класифікація ВП...
8711. Спряження вимірювальних перетворювачів з цифровими пристроями 121 KB
  Спряження вимірювальних перетворювачів з цифровими пристроями План. Введення аналогових сигналів в комп’ютер. Мультиплексори Дискретизація сигналів Класифікація сигналів Аналогова фільтрація. Цифро-аналогові пе...
8712. Виконавчі пристрої 63.5 KB
  Виконавчі пристрої План 4.1. Пристрої комутації на оптопарах 4.2. Пристрої комутації на транзисторах 4.3. Пристрої керування світлодіодами 4.4. Твердотільні реле 4.5. Крокові двигуни Виконавчий пристрій чи механізм (actuator) перетворює електричну е...
8713. Спряження комп’ютера з нестандартними зовнішніми пристроями через паралельний порт 133.5 KB
  Спряження комп’ютера з нестандартними зовнішніми пристроями через паралельний порт План. Порядок обміну даними через порт принтера (інтерфейсу Centronics). Протоколи та типи паралельного порта. Фізичний і електричний інтерфейс
8714. Розробка та програмування пристроїв спряження для послідовного інтерфейсу 225 KB
  Розробка та програмування пристроїв спряження для послідовного інтерфейсу План. Послідовна передача даних. Сигнали та розєми порту. Програмна модель послідовного порта. Електричний інтерфейс RS-232C. Способи кер...
8715. Спряження зовнішніх пристроїв з комп’ютером за допомогою шин ISA та PCI 87 KB
  Спряження зовнішніх пристроїв з компютером за допомогою шин ISAта PCI План 7.1. Будова шини ISA 7.2. Сигнали шини ISA 7.3. Цикли шини 7.1. Будова шини ISA Шина ISA (Industrial Standart Arhitecture) є фактично стандартною шиною для персон...