- •24.1. Іменування файлів у Windows
- •24.2. Створення і відкриття файлів
- •24.3. Закриття і видалення файлів
- •24.4. Запис даних у файл
- •24.5. Звільнення буферів файла
- •24.6. Читання даних з файла
- •24.7. Копіювання файла
- •24.8. Переміщення файла
- •24.9. Заміщення файла
- •24.10. Робота з покажчиком позиції файла
- •24.11. Визначення і зміна атрибутів файла
- •24.12. Визначення і зміна розмірів файла
- •24.13. Блокування файла
- •24.14. Отримання інформації про файл
24.12. Визначення і зміна розмірів файла
Перш ніж описувати функції для роботи з розміром файла, зауважимо, що розмір файла є цілим числом і для його зберігання вимагаються два значення типу dword або, іншими словами, два подвійні слова. Перше з цих подвійних слів містить старшу частину розміру файла, а друге - молодшу. Якщо розмір файла входить тільки в молодшу частину, то значення старшою встановлюється в null.
Визначити розмір файла можна за допомогою функції GetFileSize(), яка має наступний прототип:
DWORD GetFileSize(
HANDLE hFile, // дескриптор файла
LPDWORD lpFileSizeHigh); // покажчик на старшу частину розміру файла
У разі успішного завершення ця функція повертає молодшу частину розміру файла, а за адресою, вказаною в параметрі lpFileSizeHigh, записує старшу частину розміру файла. У разі невдачі функція GetFileSize() повертає значення -1, якщо значення адреси, заданої параметром lpFileSizeHigh, встановлене в null. Якщо ж значення цієї адреси не дорівнює null і функція закінчилася невдачею, то вона повертає значення -1 і функція коду останньої помилки GetLastError() поверне значення, відмінне від no_error.
Відмітимо, що для правильної роботи функції GetFileSize() потрібне, щоб файл був відкритий в режимі читання або запису.
У лістингу 24.11 приведена програма, яка визначає розмір файла, використовуючи функцію GetFileSize().
// Лістинг 24.11. Визначення розміру файла за допомогою функції GetFileSize()
#include "stdafx.h"
int main()
{
HANDLE hFile;
wchar_t lpszFileName[] = L"C:\\Users\\Shogun\\Documents\\demo_file.dat";
DWORD dwFileSize; // молодша частина розміру файла
// відкриваємо файл для читання
hFile = CreateFile(
lpszFileName, // ім'я файла
GENERIC_READ, // читання із файла
0, // монопольний доступ до файла
NULL, // захисту немає
OPEN_EXISTING, // відкриваємо існуючий файл
FILE_ATTRIBUTE_NORMAL, // звичайний файл
NULL // шаблона немає
);
// перевіряємо на успішне відкриття
if (hFile == INVALID_HANDLE_VALUE)
{
std::cerr << "Create file failed." << std::endl
<< "The last error code: " << GetLastError() << std::endl;
std::cout << "Press any key to finish.";
std::cin.get();
return 0;
}
// визначаємо розмір файла
dwFileSize = GetFileSize(hFile, NULL);
if (dwFileSize == -1)
{
std::cerr << "Get file size failed." << std::endl
<< "The last error code: " << GetLastError() << std::endl;
CloseHandle(hFile);
std::cout << "Press any key to finish.";
std::cin.get();
return 0;
}
// виводимо розмір файла
std::cout << "File size: " << dwFileSize << std::endl;
// закриваємо дескриптор файла
CloseHandle(hFile);
std::cin.get();
return 0;
}
Визначити розмір файла можна також за допомогою функції GetFileSizeEx(), яка підтримується тільки ОС Windows 2000 і Windows XP. Ця функція має наступний прототип:
BOOL GetFileSizeEx(
HANDLE hFile, // дескриптор файла
PLARGE_INTEGER lpFileSize); // розмір файла
У разі успішного завершення функція повертає ненульове значення, інакше - false.
Параметр hFile цієї функції повинен містити дескриптор файла, а параметр lpFileSize вказує на об’єднання типу large_integer, в яке функція GetFileSizeEx() записує розмір файла. Формат об’єднання типу large_integer приведений в розд. 24.10.
У лістингу 24.12 приведена програма, яка визначає розмір файла, використовуючи функцію GetFileSizeEx().
// Лістинг 24.12. Визначення розміру файла за допомогою функції GetFileSizeEx()
#include "stdafx.h"
int main()
{
HANDLE hFile;
wchar_t lpszFileName[] = L"C:\\Users\\Shogun\\Documents\\demo_file.dat";
LARGE_INTEGER liFileSize; // розмір файла
// відкриваємо файл для читання
hFile = CreateFile(
lpszFileName, // ім'я файла
GENERIC_READ, // читання із файла
0, // монопольний доступ до файла
NULL, // захисту немає
OPEN_EXISTING, // відкриваємо існуючий файл
FILE_ATTRIBUTE_NORMAL, // звичайний файл
NULL // шаблона немає
);
// перевіряємо на успішність відкриття
if (hFile == INVALID_HANDLE_VALUE)
{
std::cerr << "Create file failed." << std::endl
<< "The last error code: " << GetLastError() << std::endl;
std::cout << "Press any key to finish.";
std::cin.get();
return 0;
}
// визначаємо розмір файла
if (!GetFileSizeEx(hFile, &liFileSize))
{
std::cerr << "Get file size failed." << std::endl
<< "The last error code: " << GetLastError() << std::endl;
CloseHandle(hFile);
std::cout << "Press any key to finish.";
std::cin.get();
return 0;
}
// виводимо розмір файла
std::cout << "File size: " << liFileSize.LowPart << std::endl;
// закриваємо дескриптор файла
CloseHandle(hFile);
std::cin.get();
return 0;
}
Змінити розмір файла можна за допомогою функції SetEndOfFile(), яка має наступний прототип:
BOOL SetEndOfFile(
HANDLE hFile); // дескриптор файла
У разі успішного завершення ця функція повертає ненульове значення, інакше - false. Єдиним параметром функції є дескриптор файла, розмір якого змінюється. При цьому відмітимо, що файл має бути відкритий в режимі запису.
Функція SetEndOfFile() працює таким чином. Вона пересуває маркер кінця файла eof на позицію, яку містить покажчик позиції файла. Якщо покажчик позиції файла вказує на запис, який не є останнім, то всі записи, які знаходяться за поточним записом, відкидаються. Таким чином, у цьому випадку вміст файла урізається.
Якщо ж покажчик позиції файла вказує за межі файла, то обсяг файла розширюється за рахунок додавання нових кластерів до нього. При цьому вміст доданих кластерів не визначений. У лістингу 24.13 наведений приклад програми, яка зменшує розмір файла в два рази.
// Лістинг 24.13. Зміна розміру файла
#include "stdafx.h"
int main()
{
HANDLE hFile; // дескриптор файла
wchar_t lpszFileName[] = L"C:\\Users\\Shogun\\Documents\\demo_file.dat";
DWORD dwFileSize; // розмір файла
long p; // покажчик позиції
// відкриваємо файл для читання
hFile = CreateFile(
lpszFileName, // ім'я файла
GENERIC_WRITE, // запис у файл
0, // монопольний доступ до файла
NULL, // захисту немає
OPEN_EXISTING, // відкриваємо існуючий файл
FILE_ATTRIBUTE_NORMAL, // звичайний файл
NULL // шаблона немає
);
// перевіряємо на успішність відкриття
if (hFile == INVALID_HANDLE_VALUE)
{
std::cerr << "Create file failed." << std::endl
<< "The last error code: " << GetLastError() << std::endl;
std::cout << "Press any key to finish.";
std::cin.get();
return 0;
}
// визначаємо розмір файла
dwFileSize = GetFileSize(hFile, NULL);
if (dwFileSize == -1)
{
std::cerr << "Get file size failed." << std::endl
<< "The last error code: " << GetLastError() << std::endl;
CloseHandle(hFile);
std::cout << "Press any key to finish.";
std::cin.get();
return 0;
}
// виводимо на консоль розмір файла
std::cout << "Old file size: " << dwFileSize << std::endl;
// зменшуємо розмір файла вдвічі
dwFileSize /= 2;
// зсуваємо покажчик позиції файла
p = SetFilePointer(hFile, dwFileSize, NULL, FILE_BEGIN);
if(p == -1)
{
std::cerr << "Set file pointer failed." << std::endl
<< "The last error code: " << GetLastError() << std::endl;
CloseHandle(hFile);
std::cout << "Press any key to finish.";
std::cin.get();
return 0;
}
// встановлюємо новий розмір файла
if (!SetEndOfFile(hFile))
{
std::cerr << "Set end of file failed." << std::endl
<< "The last error code: " << GetLastError() << std::endl;
CloseHandle(hFile);
std::cout << "Press any key to finish.";
std::cin.get();
return 0;
}
// визначаємо новий розмір файла
dwFileSize = GetFileSize(hFile, NULL);
if (dwFileSize == -1)
{
std::cerr << "Get file size failed." << std::endl
<< "The last error code: " << GetLastError() << std::endl;
CloseHandle(hFile);
std::cout << "Press any key to finish.";
std::cin.get();
return 0;
}
// виводимо на консоль розмір файла
std::cout << "New file size: " << dwFileSize << std::endl;
// закриваємо дескриптор файла
CloseHandle(hFile);
std::cin.get();
return 0;
}
