24 Робота з файлами у Windows.pptx
- Количество слайдов: 32
Робота з файлами у Windows Лекція Підготував Шахрайчук М. І. 09. 02. 2018 1
Створення і відкриття файлів Для створення нових або відкриття вже існуючих файлів використовується функція Create. File(), яка має наступний прототип: HANDLE Create. File( LPCTSTR lp. File. Name, // ім'я файла DWORD dw. Desired. Access, // спосіб доступу DWORD dw. Share. Mode, // режим спільного доступу LPSECUTITY_ATTRIBUTES Ip. Securuty. Attributes, // атрибути захисту DWORD dw. Creation. Disposition, // створення або відкриття файла DWORD dw. Flags. And. Attributes, // прапорці та атрибути HANDLE h. Template. File // файл атрибутів ); При успішному завершенні функція повертає дескриптор файла, інакше - INVALID_HANDLE_VALUE. 09. 02. 2018 2
Створення і відкриття файлів У параметрі lp. File. Name задається покажчик на символьний рядок, який містить повне ім’я файла. Якщо повне ім’я файла не вказане, то файл із заданим ім’ям створюється або шукається в поточному каталозі. Параметр dw. Desired. Access задає спосіб доступу до файла і може приймати будь-яку комбінацію наступних значень: Ø 0 - застосування може тільки визначати атрибути пристрою; Ø GENERIC_READ – дозволяється тільки читання даних з файла; Ø GENERIC_WRITE – дозволяється тільки запис даних у файл. Це загальні або родові режими доступу до файла. Існують також й інші режими, значення яких залежать від доступу, заданого при визначенні атрибутів захисту файла. Ці режими будуть розглянуті в розділі присвяченому захисту файлів. Поки ж вважатимемо, що файл отримує атрибути захисту за замовчуванням, що дозволяє виконувати над ним всі існуючі операції. 09. 02. 2018 3
Створення і відкриття файлів Параметр dw. Share. Mode задає режими спільного доступу до файла. Якщо значення цього параметра дорівнює нулю, то файл не може використовуватися для спільного доступу. Інакше параметр dw. Share. Mode може приймати будь-яку комбінацію наступних значень: Ø FILE_SHARE_READ - файл може використовуватися тільки для спільного читання декількома програмами; Ø FILE_SHARE_WRITE - файл може використовуватися тільки для спільного запису декількома програмами; Ø FILE_SHARE_DELETE - файл може використовуватися декількома програмами за умови, що кожна з них має дозвіл на видалення цього файла. 09. 02. 2018 4
Створення і відкриття файлів Параметр Ip. Securuty. Attributes задає атрибути захисту файла. Нехай поки він = NULL – т. т. атрибути встановлюються за замовчуванням (дескриптор не спадкується і файл відкритий для доступу всім користувачам). Параметр dw. Creation. Disposition задає дії, які треба виконати при створенні або відкритті файла. Цей параметр може приймати одне з наступних значень: Ø CREATE_NEW - створити новий файл, якщо такий файл вже існує, то функція завершується невдачею; Ø CREATE_ALWAYS - створити новий файл, якщо такий файл вже існує, то він знищується і створюється новий; Ø OPEN_EXISTING - відкрити існуючий файл, якщо такий файл не існує, то функція завершується невдачею; Ø OPEN_ALWAYS - відкрити файл, якщо такий файл не існує, то створюється новий файл; Ø TRUNCATE_EXISTING - відкрити файл і знищити його вміст, якщо такий файл існує, то функція завершується невдачею. 09. 02. 2018 5
Створення і відкриття файлів Відмітимо, що в останньому випадку, викликаючий процес повинен мати права запису у файл, тобто в параметрі dw. Desired. Access має бути встановлений прапорець GENERIC_WRITE. У параметрі dw. Flags. And. Attributes задаються прапорці та атрибути. Вони керують властивостями файла і можуть бути комбінацією наступних значень: Ø FILE_ATTRIBUTE_ARCHIVE - архівний файл, який містить службову інформацію; Ø FILE_ATTRIBUTE_ENCRYPTED - зашифрований файл; Ø FILE_ATTRIBUTE_HIDDEN - прихований файл; Ø FILE_ATTRIBUTE_NORMAL - звичайний файл, який не має інших атрибутів; Ø FILE_ATTRIBUTE_NOT_CONTENT_INDEXED - вміст файла не індексований; 09. 02. 2018 6
Створення і відкриття файлів Ø FILE_ATTRIBUTE_OFFLINE – файл знаходиться в допоміжній пам’яті; Ø FILE_ATTRIBUTE_READONLY - файл можна тільки читати; Ø FILE_ATTRIBUTE_SYSTEM - файл використовується ОС; Ø FILE_ATTRIBUTE_TEMPORARY - файл використовується для тимчасового зберігання даних. Зробимо декілька зауважень відносно деяких атрибутів файлів. Спочатку відмітимо, що зашифровані файли не можуть мати також атрибуту FILE_ATTRIBUTE_SYSTEM. Тепер зауважимо, що атрибут FILE_ATTRIBUTE_NORMAL повинен використовуватися тільки один, а не в комбінації з іншими атрибутами. 09. 02. 2018 7
Створення і відкриття файлів Крім того, параметр dw. Flags. And. Attributes може бути комбінацією наступних управляючих прапорців: Ø FILE_FLAG_WRITE_THROUGH - запис даних безпосередньо на диск, без кешування; Ø FILE_FLAG_OVERLAPPED - забезпечується асинхронне виконання операцій читання і запису; Ø FILE_FLAG_NO_BUFFERING - не використовувати буферизацію при доступі до файла; Ø FILE_FLAG_RANDOM_ACCESS - програма припускає вибирати записи з файла випадковим чином; Ø FILE_FLAG_SEQUENTIAL_SCAN - програма скануватиме файл послідовно; Ø FILE_FLAG_DELETE_ON_CLOSE - файл буде видалений після того, як усі дескриптори цього файла будуть закриті; 09. 02. 2018 8
Створення і відкриття файлів Ø FILE_FLAG_BACKUP_SEMANTICS - резервний файл; Ø FILE_FLAG_POSIX_SEMANTICS - доступ до файла здійснюватиметься за стандартом POSIX; Ø FILE_FLAG_OPEN_REPARSE_POINT - при доступі до файла використовується системний фільтр; Ø FILE_FLAG_OPEN_NO_RECALL - при використанні ієрархічної системи управління пам’яттю файл не повинен читатися в ОП, а залишатися на нижньому рівні ієрархії. Параметр h. Template. File використовується при створенні файла, атрибути якого повинні відповідати атрибутам раніше створеного файла. У цьому випадку параметр h. Template. File повинен містити дескриптор файла, атрибути якого копіюються в атрибути створюваного файла. В інших параметрах, окрім параметра dw. Creation. Disposition, може бути встановлене значення 0. 09. 02. 2018 9
Закриття і видалення файлів Для закриття доступу до файла, як і для закриття доступу до будь-якого іншого об’єкта ядра, використовується функція Close. Handle(), єдиним параметром якої є дескриптор відкритого файла. Для фізичного видалення файла з диска використовується функція Delete. File(), яка має наступний прототип: BOOL Delete. File( LPCTSTR Ip. File. Name); // ім’я файла Параметр Ip. File. Name є покажчиком на рядок, який є повним шляхом до файла. При успішному завершенні функція повертає ненульове значення, інакше - FALSE. У лістингу 24. 1 приведена програма, яка видаляє файл з ім’ям demo_file. dat, який розташований в кореневому каталозі на диску С: . 09. 02. 2018 10
Закриття і видалення файлів // Лістинг 24. 1. Видалення файла #include "stdafx. h" int main() { wchar_t lpsz. Name. File[] = L"C: \demo_file. dat"; // видаляємо файл if(!Delete. File(lpsz. Name. File)) { std: : cerr << "Delete file failed. " << std: : endl << "The last error code: " << Get. Last. Error() << std: : endl; std: : cout << "Press any key to finish. "; std: : cin. get(); return 0; } std: : cout << "The file is deleted. " << std: : endl; return 0; } 09. 02. 2018 11
Запис даних у файл Для запису даних у файл служить функція Write. Fiie(), причому відмітимо, що ця функція може використовуватися як для синхронного, так і для асинхронного запису даних. Розглянемо тільки синхронний запис даних у файл. У цьому випадку дані записуються у файл послідовно - байт за байтом, і покажчик файла пересувається у міру запису даних на нову позицію. Асинхронне введення-виведення даних буде розглянуто пізніше. 09. 02. 2018 12
Запис даних у файл Тепер розглянемо функцію Write. File() детальніше. Ця функція має наступний прототип BOOL Write. File( HANDLE h. File, // дескриптор файла LPCVOID lp. Buffer, // покажчик на буфер даних DWORD n. Number. Of. Bytes. To. Write, // число байтів, які записуються LPDWORD lp. Number. Of. Bytes. Written, // число записаних байтів LPOVERLAPPED lp. Overlapped // використовується при асинхронному записі ); У разі успішного завершення функція повертає ненульове значення, інакше - FALSE. 09. 02. 2018 13
Запис даних у файл Параметр h. File містить дескриптор файла, причому файл має бути відкритий в режимі запису. Параметр lp. Buffer повинен вказувати на область пам’яті, в яку читатимуться дані. Параметр n. Number. Of. Bytes. To. Write повинен містити число байт, які передбачається записати у файл. Параметр lp. Number. Of. Bytes. Written повинен містити адресу пам’яті, в яку функція Write. File() помістить число фактично записаних байт. При виконанні функції Write. File() ОС записує за цією адресою нуль, перш ніж виконати запис даних у файл. Параметр lp. Overlapped встановлюємо в NULL, бо використовується синхронний запис. У лістингу 24. 2 приведена програма, яка створює файл і записує в нього послідовність цілих чисел. 09. 02. 2018 14
Запис даних у файл // 24_02_Create. Write. File. cpp: головний файл проекту. // Лістинг 24. 2. Створення файла і запис в нього даних #include "stdafx. h" int main() { HANDLE h. File; wchar_t lpsz. File. Name[] = L"C: \demo_file. dat"; // створимо файл для запису даних h. File = Create. File( lpsz. File. Name, // ім'я файла GENERIC_WRITE, // запис у файл 0, // монопольний доступ до файла NULL, // захисту немає CREATE_NEW, // створюємо новий файл FILE_ATTRIBUTE_NORMAL, // звичайний файл NULL // шаблона немає ); 09. 02. 2018 15
Запис даних у файл // перевіряємо на успішність створення if (h. File == INVALID_HANDLE_VALUE) { std: : cerr << "Create file failed. " << std: : endl << "The last error code: " << Get. Last. Error() << std: : endl; std: : cout << "Press any key to finish. "; std: : cin. get(); return 0; } // пишемо дані у файл for (int i = 0; i < 10; ++i) { DWORD dw. Bytes. Write; if (!Write. File( h. File, // дескриптор файла &i, // адреса буфера, звідки здійснюється запис sizeof(i), // число байтів, які записуються &dw. Bytes. Write, // число записаних байтів (LPOVERLAPPED)NULL // запис синхронний )) 09. 02. 2018 16
Запис даних у файл } { std: : cerr << "Write file failed. " << std: : endl << "The last error code: " << Get. Last. Error() << std: : endl; Close. Handle(h. File); std: : cout << "Press any key to finish. "; std: : cin. get(); return 0; } } // закриваємо дескриптор файла Close. Handle(h. File); std: : cout << "The file is created and written. " << std: : endl; std: : cin. get(); return 0; 09. 02. 2018 17
Звільнення буферів файла Часто декілька застосувань мають спільний доступ до одного і того ж файла. При цьому може знадобитися, щоб застосування, яке читає дані з файла, мало доступ до останньої версії цього файла. Для цього потрібно, щоб застосування, яке змінює вміст файла, фіксувало зміну файла після обробки потрібних записів. Через те, що не виключено, що останні оброблені записи зберігаються в буфері файла, то в цьому випадку потрібно звільнити буфер від записів. Виконати цю операцію можна за допомогою функції Flush. File. Buffers(), яка має наступний прототип: BOOL Flush. File. Buffers( HANDLE h. File); // дескриптор файла При успішному завершенні функція повертає ненульове значення, інакше - FALSE. У Лістингу 24. 3 приведена програма, в якій функція Flush. File. Buffers() використовується для скидання даних з буферів у файл після запису половини файла. 09. 02. 2018 18
Звільнення буферів файла // 24_03_Flush. File. Buffers. cpp: головний файл проекту. // Лістинг 24. 3 Звільнення буферів файла #include "stdafx. h" int main() { HANDLE h. File; wchar_t lpsz. File. Name[] = L"C: \Users\Shogun\Documents\demo_file. txt"; // створюємо файл для запису даних h. File = Create. File( lpsz. File. Name, // ім'я файла GENERIC_WRITE, // запис у файл FILE_SHARE_READ, // розділюване читання файла NULL, // захисту немає CREATE_ALWAYS, // створюємо новий файл FILE_ATTRIBUTE_NORMAL, // звичайний файл NULL // шаблону немає ); 09. 02. 2018 19
Звільнення буферів файла )) // перевіряємо на успішність створення if (h. File == INVALID_HANDLE_VALUE) { std: : cerr << "Create file failed. " << std: : endl << "The last error code: " << Get. Last. Error() << std: : endl; std: : cout << "Press any key to finish. "; std: : cin. get(); return 0; } // пишемо дані у файл for (int i = 0; i < 10; ++i) { DWORD dw. Bytes. Write; if (!Write. File( h. File, // дескриптор файла &i, // адреса буфера, звідки йде запис sizeof(i), // число байтів, які записуються &dw. Bytes. Write, // число байтів, які записано (LPOVERLAPPED)NULL // запис синхронний 09. 02. 2018 20
Звільнення буферів файла { std: : cerr << "Write file failed. " << std: : endl << "The last error code: " << Get. Last. Error() << std: : endl; Close. Handle(h. File); std: : cout << "Press any key to finish. "; std: : cin. get(); return 0; } // якщо досягнули середини файла, то звільняємо буфер if(i == 5) { if(!Flush. File. Buffers(h. File)) { std: : cerr << "Flush file buffers failed. " << std: : endl <<"The last error code: " << Get. Last. Error() << std: : endl; Close. Handle(h. File); std: : cout << "Press any key to finish. "; std: : cin. get(); return 0; } 09. 02. 2018 21
Звільнення буферів файла } // тепер можна переглянути вміст файла std: : cout << "A half of the file is written. " << std: : endl << "Press any key to continue. "; std: : cin. get(); } } // закриваємо дескриптор файла Close. Handle(h. File); std: : cout << "The file is created and written. " << std: : endl; std: : cin. get(); return 0; 09. 02. 2018 22
Звільнення буферів файла // тепер можна переглянути вміст файла std: : cout << "A half of the file is written. " << std: : endl << "Press any key to continue. "; std: : cin. get(); } } // закриваємо дескриптор файла Close. Handle(h. File); std: : cout << "The file is created and written. " << std: : endl; std: : cin. get(); return 0; } На завершення зауважимо, що можна відмінити режим буферизації файла, встановивши прапорець FILE_FLAG_NO_BUFFERING в параметрі dw. Flags. And. Attributes. Проте в цьому випадку довжина записуваних або зчитуваних даних з файла має бути кратна розміру сектора. Наприклад, в ОС Windows довжина сектора дорівнює 512 байт. 09. 02. 2018 23
Читання даних із файла Читати дані із файла може функція Read. File(), яка може використовуватися як для синхронного, так і асинхронного читання даних. Розглянемо тільки синхронне читання даних з файла. Асинхронне введення-виведення даних буде розглянуто пізніше. Розглянемо функцію Read. File(), яка має наступний прототип: BOOL Read. File( HANDLE h. File, // дескриптор файла LPVOID lp. Buffer, // покажчик на буфер даних DWORD n. Number. Of. Bytes. To. Read, // число байтів, які будуть читатися LPDWORD lp. Number. Of. Bytes. Read, // число зчитаних байтів LPOVERLAPPED lp. Overlapped // використовується при асинхронному записі ); При успішному завершенні функція повертає ненульове значення, інакше - FALSE. 09. 02. 2018 24
Читання даних із файла Параметр h. File містить дескриптор файла, причому файл має бути відкритий в режимі читання. Параметр lp. Buffer вказує на область пам’яті, з якої читатимуться дані. Параметр n. Number. Of. Bytes. To. Read містить число байтів, які передбачається читати з файла. Параметр lp. Number. Of. Bytes. Read містить адресу пам’яті, в яку функція Read. File() помістить число фактично зчитаних байтів. Параметр lp. Overlapped встановлюємо в NULL, бо читання синхронне. Детально асинхронне введення-виведення даних буде розглянуте пізніше. У лістингу 24. 4 приведена програма, яка читає дані з файла, створеного програмою з лістингу 24. 2, і виводить ці дані на консоль. 09. 02. 2018 25
Читання даних із файла // 24_04_Read. File. cpp: головний файл проекту. // Лістинг 24. 4. Відкриття файла і читання з нього даних #include "stdafx. h" int main() { HANDLE h. File; wchar_t lpsz. File. Name[] = L"C: \Users\Shogun\Documents\demo_file. txt"; // відкриваємо файл для читання h. File = Create. File( lpsz. File. Name, // ім'я файла GENERIC_READ, // читання із файла 0, // монопольний доступ до файла NULL, // захисту немає OPEN_EXISTING, // відкриваємо існуючий файл FILE_ATTRIBUTE_NORMAL, // звичайний файл NULL // шаблона немає ); 09. 02. 2018 26
Читання даних із файла // перевіряємо на успішність відкриття if (h. File == INVALID_HANDLE_VALUE) { std: : cerr << "Create file failed. " << std: : endl << "The last error code: " << Get. Last. Error() << std: : endl; std: : cout << "Press any key to finish. "; std: : cin. get(); return 0; } 09. 02. 2018 27
Читання даних із файла // читаємо дані із файла for (; ; ) { DWORD dw. Bytes. Read; int n; // читаємо один запис if (!Read. File( h. File, // дескриптор файла &n, // адреса буфера, куди читаємо дані sizeof(n), // число байтів, які читаємо &dw. Bytes. Read, // число прочитаних байтів (LPOVERLAPPED)NULL // читання синхронне )) 09. 02. 2018 28
Читання даних із файла { std: : cerr << "Read file failed. " << std: : endl << "The last error code: " << Get. Last. Error() << std: : endl; Close. Handle(h. File); std: : cout << "Press any key to finish. "; std: : cin. get(); return 0; } // перевіряємо на кінець файла if (dw. Bytes. Read == 0) // якщо так, то виходимо із циклу break; else // інакше виводимо запис на консоль std: : cout << n << ' '; } 09. 02. 2018 29
Читання даних із файла std: : cout << std: : endl; // закриваємо дескриптор файла Close. Handle(h. File); std: : cout << "The file is opened and read. " << std: : endl; std: : cin. get(); return 0; } У зв’язку з цією програмою відмітимо обробку кінця файла. Досягши кінця файла і запиті на читання запису функція Read. File() повертає ненульове значення і при цьому встановлює значення числа прочитаних байтів в 0. 09. 02. 2018 30
Копіювання файла Для копіювання файлів використовується функція Copy. File(), яка має наступний прототип: BOOL Copy. File( LPCTSTR lp. Existing. File. Name, // ім’я існуючого файла LPCTSTR lp. New. File. Name, // ім’я нового файла BOOL b. File. If. Exists); // дії у разі існування файла При успішному завершенні функція повертає ненульове значення, інакше - FALSE. При цьому відмітимо, що функція Copy. File() копіює для нового файла також і атрибути доступу старого файла, але атрибути безпеки не копіюються. Параметр lp. Existing. File. Name вказує на рядок, який містить ім’я копійованого файла. Параметр lp. New. File. Name повинен вказувати на рядок з ім’ям файла, в який копіюватиметься існуючий файл. При цьому відмітимо, що новий файл створюється самою функцією Copy. File(). 09. 02. 2018 31
fgets() Назад Приклад: Ця програма використовує fgets() для відображення вмісту текстового файла, на який вказує перший аргумент командного рядка: #include <stdio. h> #include <stdlib. h> int main(int argc, char *argv[]) { FILE *fp; char str[128]; if ((fp=fopen(argv[1], "r") )==NULL) { printf("Cannot open file. n"); exit (1); } while(!feof(fp)) { if (fgets(str, 126, fp)) printf("%s", str); } fclose(fp); return 0; } 09. 02. 2018 32
24 Робота з файлами у Windows.pptx