
24_3 Блокування файла.pptx
- Количество слайдов: 29
Робота з файлами у Windows (Блокування файла і далі ) Лекція Підготував Шахрайчук М. І. 09. 02. 2018 1
Блокування файла Часто декілька застосувань мають спільний доступ до одного і того ж файла. При цьому може буде потрібно, щоб застосування, яке змінює дані у файлі, мало до цього файла монопольний доступ. Для цього треба блокувати увесь файл або тільки його частину для доступу іншим застосуванням. Для цих цілей використовується функція Lock. File(), яка має наступний прототип: BOOL Lock. File( HANDLE h. File, // дескриптор файла DWORD dw. File. Offset. Low, // молодша частина зміщення DWORD dw. File. Offset. High, // старша частина зміщення DWORD n. Number. Of. Bytes. To. Lock. Low, // молодша частина числа байтів DWORD n. Number. Of. Bytes. Ti. Lock. High); // старша частина числа байтів 09. 02. 2018 2
Блокування файла У разі успішного завершення вона повертає ненульове значення, інакше - FALSE. Опишемо параметри функції. q h. File містить дескриптор файла. Файл має бути відкритий в режимі запису або читання. q dw. File. Offset. Low і dw. File. Offset. High мають бути встановлені відповідно: молодша і старша частини зміщення від початку файла у байтах. q n. Number. Of. Bytes. To. Lock. Low і n. Number. Of. Bytes. Ti. Lock. High мають бути встановлені відповідно: старша і молодша частини довжини області файла, яка блокується для монопольного доступу застосуванням. Функція Unlock. File(), відміняє блокування області: BOOL Unlock. File( HANDLE h. File, // дескриптор файла DWORD dw. File. Offset. Low, // молодша частина зміщення DWORD dw. File. Offset. High, // старша частина зміщення DWORD n. Number. Of. Bytes. To. Lock. Low, // молодша частина числа байтів DWORD n. Number. Of. Bytes. Ti. Lock. High); // старша частина числа байтів 09. 02. 2018 3
Блокування файла Вдале завершення функції повертає ненульове значення, інакше - FALSE. Її параметри аналогічні таким для Lock. Fi. Le(). // Лістинг 24. 14. Блокування і розблокування файла #include "stdafx. h" int main() { HANDLE h. File; wchar_t lpsz. File. Name[] = L"C: \Users\Shogun\Documents\demo_file. dat"; DWORD dw. File. Size; // відкриваємо файл для запису h. File = Create. File( lpsz. File. Name, // ім'я файла GENERIC_WRITE, // запис у файл 0, // монопольний доступ до файла NULL, // захисту немає OPEN_EXISTING, // відкриваємо існуючий файл FILE_ATTRIBUTE_NORMAL, // звичайний файл NULL); // шаблона немає 09. 02. 2018 4
Блокування файла // перевіряємо на успішність відкриття 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; } // визначаємо розмір файла dw. File. Size = Get. File. Size(h. File, NULL); if (dw. File. Size == -1) { std: : cerr << "Get file size 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 5
Блокування файла // блокуємо файл if (!Lock. File(h. File, 0, 0, dw. File. Size, 0)) { std: : cerr << "Lock 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; } std: : cout << "Now the file is locked. " << std: : endl << "Press any key to continue. " << std: : endl; std: : cin. get(); 09. 02. 2018 6
Блокування файла } // розблоковуємо файл if (!Unlock. File(h. File, 0, 0, dw. File. Size, 0)) { std: : cerr << "Unlock 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; } std: : cout << "Now the file is unlocked. " << std: : endl << "Press any key to continue. " << std: : endl; std: : cin. get(); // закриваємо дескриптор файла Close. Handle(h. File); return 0; 09. 02. 2018 7
Блокування файла На завершення цього розділу зробимо декілька зауважень відносно використання функцій Lock. File() і Unlock. File(). Передусім, відмітимо, що якщо застосування видає запит на блокування області файла, яка вже заблокована самим застосуванням, то виконання функції Lock. File() завершиться невдачею. Крім того, блокування і розблокування файлів повинні співпадати по областях. 09. 02. 2018 8
Отримання інформації про файл Щоб отримати інформацію про файл, можна використовувати функцію Get. File. Information. By. Handle() : BOOL Get. File. Information. By. Handle( HANDLE h. File, // дескриптор файла LPBY_HANDLE_FILE_INFORMATION lp. Filelnformation); // покажчик на інформацію При успішному завершенні ця функція повертає ненульове значення, інакше - FALSE. У параметрі h. File цієї функції має бути дескриптор файла, інформацію про який потрібно отримати. Файл може бути відкритий в будь-якому режимі доступу. Параметр lp. File. Information повинен вказувати на структуру типу BY_HANDLE_FILE_INFORMATION, в яку функція запише інформацію про файл. Ця структура має наступний формат: 09. 02. 2018 9
Отримання інформації про файл typedef struct _BY_HANDLE_FILE_INFORMATION { DWORD dw. File. Attributes; // атрибути файла FILETIME ft. Creation. Time; // час створення файла FILETIME ft. Last. Access. Time; // час останнього доступу до файла FILETIME ft. Last. Write. Time; // час останнього запису у файл DWORD dw. Volume. Serial. Number; // серійний номер тому DWORD n. File. Size. High; // старша частина розміру файла DWORD n. File. Size. Low; // молодша частина розміру файла DWORD n. Number. Of. Links; // число посилань на файл DWORD n. File. Index. High; // старша частина індексу файла DWORD n. Filelndex. Low; // молодша частина індексу файла } BY_HANDLE_FILE_INFORMATION, *LPBY_HANDLE_FILE_INFORMATION; У лістингу 24. 15 приведена програма, яка отримує інформацію про файл і роздруковує її. 09. 02. 2018 10
Отримання інформації про файл // Лістинг 24. 15. Отримання інформації про файл #include "stdafx. h" int main() { HANDLE h. File; wchar_t lpsz. File. Name[] = L"C: \Users\Shogun\Documents\demo_file. dat"; BY_HANDLE_FILE_INFORMATION bhfi; // інформація про файл // відкриваємо файл для читання h. File = Create. File( lpsz. File. Name, // ім'я файла 0, // отримання інформації про файл 0, // монопольний доступ до файла NULL, // захисту немає OPEN_EXISTING, // відкриваємо існуючий файл FILE_ATTRIBUTE_NORMAL, // звичайний файл NULL); // шаблона немає 09. 02. 2018 11
Отримання інформації про файл // перевіряємо на успішність відкриття 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; } // отримаємо інформацію про файл if (!Get. File. Information. By. Handle(h. File, &bhfi)) { std: : cerr << "Get file information by handle 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 12
Отримання інформації про файл // роздруковуємо інформацію про файл std: : cout << "File attributes: " << bhfi. dw. File. Attributes << std: : endl << "Creation time: high date: " << bhfi. ft. Creation. Time. dw. High. Date. Time << std: : endl << "Creation time: low date: " << bhfi. ft. Creation. Time. dw. Low. Date. Time << std: : endl << "Last access time: high date: " << bhfi. ft. Last. Access. Time. dw. High. Date. Time << std: : endl << "Last access time: low date: " << bhfi. ft. Last. Access. Time. dw. Low. Date. Time << std: : endl << "Last write time: high date: " << bhfi. ft. Last. Write. Time. dw. High. Date. Time << std: : endl << "Last write time: low date: " << bhfi. ft. Last. Write. Time. dw. Low. Date. Time << std: : endl << "Volume serial number: " << bhfi. dw. Volume. Serial. Number << std: : endl << "File size high: " << bhfi. n. File. Size. High << std: : endl << "File size low: " << bhfi. n. File. Size. Low << std: : endl << "Number of links: " << bhfi. n. Number. Of. Links << std: : endl << "File index high: " << bhfi. n. File. Index. High << std: : endl << "File index low: " << bhfi. n. File. Index. Low << std: : endl; 09. 02. 2018 13
Отримання інформації про файл } // закриваємо дескриптор файла Close. Handle(h. File); std: : cin. get(); return 0; 09. 02. 2018 14
Отримання інформації про файл Структура типу BY_HANDLE_FILE_INFORMATION містить структуру типу FILETIME, потрібну для зберігання часу. Ця структура має наступний формат: typedef struct _FILETIME { DWORD dw. Low. Date. Time; DWORD dw. High. Date. Time; // молодша частина часу // старша частина часу } FILETIME, *PFILETIME; Сам час задається в інтервалах, кожен величиною 100 наносекунд. Для користувача це незручно. Для переведення часу в зручнішу форму існує функція File. Time. To. System. Time() : BOOL File. Time. To. System. Time( CONST FILETIME *lp. File. Time, // покажчик на якийсь час у форматі "файл" LPSYSTEMTIME Ip. System. Time); // покажчик на якийсь час у форматі "система" 09. 02. 2018 15
Отримання інформації про файл У разі успішного завершення ця функція повертає ненульове значення, інакше - FALSE. Параметр lp. File. Time повинен вказувати на структуру типу FILETIME, яка містить час у форматі, який використовується для зберігання у файловій системі. Параметр Ip. System. Time повинен вказувати на структуру типу SYSTEMTIME, яка має наступний формат: typedef struct _SYSTEMTIME { WORD w. Year; // рік WORD w. Month; // місяць WORD w. Day. Of. Week; // день тижня WORD w. Day; // день WORD w. Hour; // година WORD w. Minute; // хвилина WORD w. Second; // секунда WORD w. Milliseconds; // мілісекунда } SYSTEMTIME, *LPSYSTEMTIME; 09. 02. 2018 16 16
Отримання інформації про файл У лістингу 24. 16 приведена програма, яка використовує функцію File. Time. To. System. Time() для переведення часу з формату файлової системи в системний формат. // Лістинг 24. 16. Перетворення часу в системний формат #include "stdafx. h" int main() { HANDLE h. File; wchar_t lpsz. File. Name[] = L"C: \Users\Shogun\Documents\demo_file. dat"; BY_HANDLE_FILE_INFORMATION bhfi; // інформація про файл SYSTEMTIME st; 09. 02. 2018 // системний час 17
Отримання інформації про файл // відкриваємо файл для читання h. File = Create. File( lpsz. File. Name, // ім'я файла 0, // отримання інформації про файл 0, // монопольний доступ до файла NULL, // захисту немає OPEN_EXISTING, // відкриваємо існуючий файл FILE_ATTRIBUTE_NORMAL, // звичайний файл NULL); // шаблона немає // перевіряємо на успішність відкриття 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 18
Отримання інформації про файл // отримуємо інформацію про файл if (!Get. File. Information. By. Handle(h. File, &bhfi)) { std: : cerr << "Get file information by handle failed. " << std: : endl << "The last error code: " << Get. Last. Error() << std: : endl; std: : cout << "Press any key to finish. "; std: : cin. get(); return 0; } // переводимо час створення файла в системний час if (!File. Time. To. System. Time(&(bhfi. ft. Creation. Time), &st)) { std: : cerr << "File time to system time 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 19
Отримання інформації про файл // роздруковуємо системний час std: : cout << "File creation time in system format: " << std: : endl } << "t. Year: " << st. w. Year << std: : endl << "t. Month: " << st. w. Month << std: : endl << "t. Day of week: " << st. w. Day. Of. Week << std: : endl << "t. Day: " << st. w. Day << std: : endl << "t. Hour: " << st. w. Hour << std: : endl << "t. Minute: " << st. w. Minute << std: : endl << "t. Second: " << st. w. Second << std: : endl << "t. Milliseconds: " << st. w. Milliseconds << std: : endl; // закриваємо дескриптор файла Close. Handle(h. File); std: : cin. get(); return 0; 09. 02. 2018 20
Отримання інформації про файл 09. 02. 2018 21
Отримання інформації про файл Визначити тип файла можна за допомогою функції Get. File. Type(), яка має наступний прототип: DWORD Get. File. Type( HANDLE h. File); // дескриптор файла Єдиним параметром цієї функції є дескриптор файла. Функція Get. File. Type() повертає одне з наступних значень: q FILE_TYPE_UNKNOWN - невідомий тип файла; q FILE_TYPE_DISK - дисковий файл; q FILE_TYPE_CHAR - символьний файл; q FILE_TYPE_PIPE - іменований або анонімний канал. Відмітимо, що під символьним файлом зазвичай розуміється принтер або консоль. У лістингу 24. 17 приведена програма, яка визначає тип файла, використовуючи функцію Get. File. Type(). 09. 02. 2018 22
Отримання інформації про файл // Лістинг 24. 17. Визначення типу файла #include "stdafx. h" int main() { HANDLE h. File; wchar_t lpsz. File. Name[] = L"C: \Users\Shogun\Documents\demo_file. dat"; DWORD dw. File. Type; // відкриваємо файл для читання h. File = Create. File( lpsz. File. Name, // ім'я файла 0, // отримання інформації про файл 0, // монопольний доступ до файла NULL, // захисту немає OPEN_EXISTING, // відкриваємо існуючий файл FILE_ATTRIBUTE_NORMAL, // звичайний файл NULL); // шаблона немає 09. 02. 2018 23
Отримання інформації про файл // перевіряємо на успішність відкриття 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; } // визначаємо тип файла dw. File. Type = Get. File. Type(h. File); // роздруковуємо тип файла switch (dw. File. Type) { case FILE_TYPE_UNKNOWN: std: : cout << "Unknown type file. " << std: : endl; break; 09. 02. 2018 24
Отримання інформації про файл case FILE_TYPE_DISK: std: : cout << "Disk type file. " << std: : endl; break; case FILE_TYPE_CHAR: std: : cout << "Char type file. " << std: : endl; break; case FILE_TYPE_PIPE: std: : cout << "Pipe type file. " << std: : endl; break; } default: break; } std: : cin. get(); return 0; 09. 02. 2018 25
Отримання інформації про файл На платформі Windows NT можна визначити, чи є файл виконуваним. Для цього треба використовувати функцію Get. Binary. Type(), яка має наступний прототип: BOOL Get. Binary. Type( LPCTSTR lp. Application. Name, // ім’я застосування LPDWORD lp. Binary. Type); // тип виконуваного файла Якщо файл є виконуваним, то функція повертає ненульове значення, інакше - FALSE. В lp. Application. Name встановлюється покажчик на рядок, який містить ім’я файла, який перевіряється. 09. 02. 2018 26
Отримання інформації про файл Параметр lp. Binary. Type повинен вказувати на змінну типу DWORD, в яку функція Get. Binary. Type() поміщає тип виконуваного файла. Цей тип може приймати одне з наступних значень: q SCS_32 BIT_BINARY - застосування Win 32; q SCS_DOS_BINARY - застосування MS-DOS; q SCS_OS 216_BINARY - 16 -бітове застосування OS/2; q SCS_PIF_BINARY - PIF-файл; q SCS_POSIX_BINARY - застосування POSIX; q SCS_WOW_BINARY - 16 -бітове застосування Windows. У лістингу 24. 18 приведена програма, яка визначає тип виконуваного файла, використовуючи функцію Get. Binary. Type(). 09. 02. 2018 27
Отримання інформації про файл // Лістинг 24. 18. Визначення типу виконуваного файла #include "stdafx. h" int main() { DWORD dw. Binary. Type; wchar_t lpsz. File. Name[] = L"C: \Console. Process. exe"; // визначимо тип файла if(!Get. Binary. Type(lpsz. File. Name, &dw. Binary. Type)) { std: : cerr << "Get binary type failed. " << std: : endl << "The file may not be executable. " << 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 28
Отримання інформації про файл // роздрукуємо тип файла if (dw. Binary. Type == SCS_32 BIT_BINARY) std: : cout << "The file is Win 32 based application. " << std: : endl; else std: : cout << "The file is not Win 32 based application. " << std: : endl; } std: : cin. get(); return 0; 09. 02. 2018 29
24_3 Блокування файла.pptx