Слайд 1Операційні системи. Лекція 8. Кафедра ПІ. Качко О., Дягілєва Ф.
ekachko@gmail.com
Змістовний модуль:
КЕРУВАННЯ ВВЕДЕННЯМ – ВИВЕДЕННЯМ
Розділ 2: ФАЙЛИ
Лекція 8
Файли.
Вступ
Слайд 2Операційні системи. Лекція 8. Кафедра ПІ. Качко О., Дягілєва Ф.
ekachko@gmail.com
ПИТАННЯ ДЛЯ ВИВЧЕННЯ
Створення файлів.
Використання існуючих файлів
Введення - виведення даних.
Клас для
роботи з файлом
Слайд 3Операційні системи. Лекція 8. Кафедра ПІ. Качко О., Дягілєва Ф.
ekachko@gmail.com
ФАЙЛИ. СТВОРЕННЯ ТА ВИКОРИСТАННЯ ІСНУЮЧИХ ФАЙЛІВ
HANDLE WINAPI CreateFile(
__in
LPCTSTR lpFileName,
__in DWORD dwDesiredAccess,
__in DWORD dwShareMode,
__in LPSECURITY_ATTRIBUTES lpSecurityAttributes,
__in DWORD dwCreationDisposition,
__in DWORD dwFlagsAndAttributes,
__in HANDLE hTemplateFile
);
lpFileName:
MAX_PATH (260) – WinDefs.h (
C:\ + 256 символів ) – ANSI – немає альтернативи
\\?\ - то 32767 (UNICODE)
Слайд 4Операційні системи. Лекція 8. Кафедра ПІ. Качко О., Дягілєва Ф.
ekachko@gmail.com
ФАЙЛИ. СТВОРЕННЯ ТА ВИКОРИСТАННЯ ІСНУЮЧИХ ФАЙЛІВ
dwDesiredAccess GENERIC_READ, GENERIC_WRITE
#define GR GENERIC_READ
#define
GW GENERIC_WRITE
dwShareMode - FILE_SHARE_READ, FILE_SHARE_WRITE,
FILE_SHARE_DELETE
#define FSR FILE_SHARE_READ
#define FSW FILE_SHARE_WRITE
#define FSD FILE_SHARE_DELETE
lpSecurityAttributes – 0 (NTFS)
dwCreationDisposition (CREATE_ALWAYS, CREATE_NEW, OPEN_ALWAYS, OPEN_EXISTING, TRUNCATE_EXISTING (Error, if not exist))
#define CA CREATE_ALWAYS, …
Слайд 5Операційні системи. Лекція 8. Кафедра ПІ. Качко О., Дягілєва Ф.
ekachko@gmail.com
ФАЙЛИ. СТВОРЕННЯ ТА ВИКОРИСТАННЯ ІСНУЮЧИХ ФАЙЛІВ
dwFlagsAndAttributes (FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_READONLY,
…
FILE_ATTRIBUTE_ENCRYPTED (NTFS),
FILE_FLAG_SEQUENTIAL_SCAN, FILE_FLAG_WRITE_THROUGH)
Примеры макросов
#define CREATENEWFILE(fn, flags) \
CreateFile (fn, GW, FSR, 0, CN, flags, 0);
#define CREATEFILE(fn, flags) \
CreateFile (fn, GW, FSR, 0, CA, flags, 0);
#define OPENFILEFORREAD(fn, flags) \
CreateFile (fn, GR, FSR, 0, OE, flags, 0);
#define OPENFILEFORREADWRITE(fn, flags) \
CreateFile (fn, GR|GW, FSR, 0, OA, flags, 0);
BOOL CloseHandle (h);
Слайд 6Операційні системи. Лекція 8. Кафедра ПІ. Качко О., Дягілєва Ф.
ekachko@gmail.com
ФАЙЛИ. ОПЕРАЦІЇ ВВЕДЕННЯ-ВИВЕДЕННЯ
BOOL WINAPI ReadFile(
__in
HANDLE hFile,
__out LPVOID lpBuffer,
__in DWORD nNumberOfBytesToRead,
__out_opt LPDWORD lpNumberOfBytesRead,
__inout_opt LPOVERLAPPED lpOverlapped
);
BOOL WINAPI WriteFile(
__in HANDLE hFile,
__out LPVOID lpBuffer,
__in DWORD nNumberOfBytesToRead,
__out_opt LPDWORD lpNumberOfBytesRead,
__inout_opt LPOVERLAPPED lpOverlapped
);
Слайд 7Операційні системи. Лекція 8. Кафедра ПІ. Качко О., Дягілєва Ф.
ekachko@gmail.com
МАКРОСИ ДЛЯ РОБОТИ З ФАЙЛАМИ
#define IHV INVALID_HANDLE_VALUE
#define GR GENERIC_READ
#define GW GENERIC_WRITE
#define FSR FILE_SHARE_READ
#define CA CREATE_ALWAYS
#define
CN CREATE_NEW
#define OA OPEN_ALWAYS
#define OE OPEN_EXISTING
#define FFSC FILE_FLAG_SEQUENTIAL_SCAN
#define FFWT FILE_FLAG_WRITE_THROUGH
#define CREATENEWFILE(fn, flags) CreateFile (fn, GW, FSR, 0, CN, flags, 0)
#define CREATEFILE(fn, flags) CreateFile (fn, GW, FSR, 0, CA, flags, 0)
#define OPENFILEFORREAD(fn, flags) CreateFile (fn, GR, FSR, 0, OE, flags, 0)
#define OPENFILEFORREADWRITE(fn, flags) CreateFile (fn, GR|GW, FSR, 0, OA,\ flags, 0)
Слайд 8Операційні системи. Лекція 8. Кафедра ПІ. Качко О., Дягілєва Ф.
ekachko@gmail.com
ФАЙЛИ. ПРИКЛАД. ФУНКЦІЯ ДЛЯ КОПІЮВАННЯ ФАЙЛУ
BOOL MyCopyFile (TCHAR *fSrc, TCHAR
*fDest, BOOL bExistFileError)
{
BOOL b = FALSE;
HANDLE hIn = IHV, hOut = IHV;
hIn = OPENFILEFORREAD (fSrc, FFSC);
if (bExistFileError)
hOut = CREATENEWFILE (fDest, FFSC);
else hOut = CREATEFILE (fDest, FFSC);
if (hIn != IHV && hOut != IHV)
{
BYTE Buf [16384];
DWORD dwCount;
while (1)
{
b = ReadFile (hIn, Buf, sizeof (Buf), &dwCount, 0);
if (b) b = WriteFile (hOut, Buf, dwCount, &dwCount, 0);
if (dwCount != sizeof (Buf)|| !b) break;
}
}
if (hIn != IHV) CloseHandle (hIn);
if (hOut != IHV) CloseHandle (hOut);
return b;
}
Слайд 9Операційні системи. Лекція 8. Кафедра ПІ. Качко О., Дягілєва Ф.
ekachko@gmail.com
КЛАС ДЛЯ РОБОТИ З ФАЙЛАМИ
#include
#include
#ifdef UNICODE
#define MAX_NAME_SIZE 32768
#else
#define
MAX_NAME_SIZE MAX_PATH
#endif
typedef enum {
NEWFILENOTEXIST, NEWFILE, READFILE, WRITEFILE, READWRITEFILE
}PROPERTIES;
class File
{
HANDLE h;
TCHAR fn [MAX_NAME_SIZE];
DWORD dwLastError;
public:
File (TCHAR *fName, PROPERTIES pr, DWORD flags);
BOOL Read (PBYTE Buf, size_t BufLen, LPDWORD ReadLen);
BOOL Write (PBYTE Buf, size_t BufLen, LPDWORD WriteLen);
~File ();
DWORD GetLastError (){return dwLastError;}
DWORD SetLastError (DWORD Error)
{
dwLastError = Error;
}
HANDLE GetHandle (){return h;}
VOID PrintError ();
};
Слайд 10Операційні системи. Лекція 8. Кафедра ПІ. Качко О., Дягілєва Ф.
ekachko@gmail.com
КЛАС ДЛЯ РОБОТИ З ФАЙЛАМИ
File::File (TCHAR *fn, PROPERTIES pr, DWORD
flags)
{
h = IHV; dwLastError = 0;
switch (pr)
{
case NEWFILENOTEXIST: h = CREATENEWFILE(fn, flags); break;
case NEWFILE: h = CREATEFILE(fn, flags); break;
case READFILE: h = OPENFILEFORREAD(fn, flags); break;
case READWRITEFILE: h = OPENFILEFORREADWRITE(fn, flags); break;
case WRITEFILE: h = OPENFILEFORREADWRITE (fn, flags); break;
}
if (h == IHV) dwLastError = GetLastError ();
}
p
File::~File ()
{
if (h != IHV) CloseHandle (h);
}
Слайд 11Операційні системи. Лекція 8. Кафедра ПІ. Качко О., Дягілєва Ф.
ekachko@gmail.com
КЛАС ДЛЯ РОБОТИ З ФАЙЛАМИ
BOOL File::Read (PBYTE Buf, size_t BufLen,
LPDWORD ReadLen)
{
return ReadFile (h, Buf, BufLen, ReadLen, 0);
}
BOOL File::Write (PBYTE Buf, size_t BufLen, LPDWORD WriteLen)
{
return WriteFile (h, Buf, BufLen, WriteLen, 0);
}
VOID File::PrintError ()
{
:: PrintError (dwLastError);
}
Слайд 12Операційні системи. Лекція 8. Кафедра ПІ. Качко О., Дягілєва Ф.
ekachko@gmail.com
КОПІЮВАННЯ ФАЙЛІВ ТА КЛАСИ
BOOL MyClassCopyFile (TCHAR *fSrc, TCHAR *fDest, BOOL
bExistFileError)
{
File f1 (fSrc, READFILE, FFSC);
File f2 (fDest, WRITEFILE, FFSC);
BOOL b = f1.GetLastError() == 0 && f2.GetLastError ()==0;
if (b)
{
BYTE Buf [16384]; DWORD dwCount;
while (1)
{
b = f1.Read (Buf, sizeof (Buf), &dwCount);
if (b) b = f2.Write (Buf, dwCount, &dwCount);
if (dwCount != sizeof (Buf)|| !b)
break;
}
}
return b;
}
Слайд 13Операційні системи. Лекція 8. Кафедра ПІ. Качко О., Дягілєва Ф.
ekachko@gmail.com
СТАНДАРТНІ ФУНКЦІЯ КОПІЮВАННЯ
BOOL WINAPI CopyFile(
__in LPCTSTR lpExistingFileName,
__in
LPCTSTR lpNewFileName,
__in BOOL bFailIfExists );
BOOL WINAPI CopyFileEx(
__in LPCTSTR lpExistingFileName,
__in LPCTSTR lpNewFileName,
__in LPPROGRESS_ROUTINE lpProgressRoutine,
__in LPVOID lpData, // Параметр функції
__in LPBOOL pbCancel, // FALSE - операція була відмінена
__in DWORD dwCopyFlags // Флаги копіювання.
);
Флаги :
COPY_FILE_FAIL_IF_EXISTS
pbCancel - чтобы много порций – исходное FALSE
Слайд 14ПОРІВНЯННЯ СТАНДАРТНИХ ФУНКЦІЙ МОВИ С ТА WINDOWS
BOOL StandatrCopyFile (TCHAR *Src,
TCHAR *Dest){
BOOL b = FALSE;
FILE * f1 = _tfopen (Src,
_T("rb")); FILE * f2 = _tfopen (Dest, _T("wb"));
if (f1 && f2){
BYTE Buffer [65536];
while (1){
DWORD dwCount1 = fread (Buffer, 1, sizeof (Buffer), f1);
DWORD dwCount2 = fwrite (Buffer, 1, dwCount1, f2);
b = dwCount1 == dwCount2; if (!b) break;
if (dwCount1 != sizeof (Buffer)) break;
}
}
if (f1) fclose (f1); if (f2) fclose (f2);
return b;
} Для файлу розміром 2.4 МБ прискорення в разі функцій Windows в >1.5 рази
Операційні системи. Лекція 8. Кафедра ПІ. Качко О., Дягілєва Ф. ekachko@gmail.com
Слайд 15Операційні системи. Лекція 8. Кафедра ПІ. Качко О., Дягілєва Ф.
ekachko@gmail.com
ФУНКЦІЯ CopyProgressRoutine
DWORD CALLBACK CopyProgressRoutine(
[in]
LARGE_INTEGER TotalFileSize,
[in] LARGE_INTEGER TotalBytesTransferred,
[in] LARGE_INTEGER StreamSize,
[in] LARGE_INTEGER StreamBytesTransferred,
[in] DWORD dwStreamNumber, // NTFS
[in] DWORD dwCallbackReason,// CALLBACK_CHUNK_FINISHED,
CALLBACK_STREAM_SWITCH
[in] HANDLE hSourceFile,
[in] HANDLE hDestinationFile,
[in] LPVOID lpData - параметр
);
LARGE_INTEGER:
typedef union {
struct {
DWORD LowPart; LONG HighPart;
} u;
LONGLONG QuadPart;
} LARGE_INTEGER, *PLARGE_INTEGER;
Слайд 16Операційні системи. Лекція 8. Кафедра ПІ. Качко О., Дягілєва Ф.
ekachko@gmail.com
ОБРОБКА ПОДІЙ, ПОВЯЗАНИХ З КОПІЮВАННЯМ ФАЙЛІВ. ПРИКЛАД
DWORD CALLBACK CopyProgressRoutine(
…){
static int
por = 0;
_tprintf (_T("Porciya #%d Copy %I64d from %I64d Bytes\n"), por++, TotalBytesTransferred.QuadPart, TotalFileSize.QuadPart);
_tprintf (_T("dwStreamNumber = %d\nStreamSize = %I64d\nStreamBytesTransferred = %I64d\n"),
dwStreamNumber, StreamSize, StreamBytesTransferred );
return 0;} // 64 К
Слайд 17Операційні системи. Лекція 8. Кафедра ПІ. Качко О., Дягілєва Ф.
ekachko@gmail.com
ЗАПИС ДАНИХ В БУФЕР
Використовується, якщо необхідно моделювати введення символів.
Приклад. Треба
зробити “ролік”, в якому показується робота програми, щоб дані для програми вводилися автоматично.
BOOL WINAPI WriteConsoleInput( __in HANDLE hConsoleInput, __in const INPUT_RECORD* lpBuffer, __in DWORD nLength, __out LPDWORD lpNumberOfEventsWritten );
MAXCOUNT = 65536 / sizeof (INPUT_RECORD)
Слайд 18Операційні системи. Лекція 8. Кафедра ПІ. Качко О., Дягілєва Ф.
ekachko@gmail.com
ЗАПИС ДАНИХ В БУФЕР. ФОРМУВАННЯ БУФЕРУ
int SetKeyEvents (HANDLE hin, INPUT_RECORD
*buf){
INPUT_RECORD *pCur = buf; DWORD NumberOfEventsRead; int i;
do{
ReadConsoleInput( hin, pCur, MAX_PATH, &NumberOfEventsRead);
printf ("NumberOfEventsRead = %d\n", NumberOfEventsRead);
for (i = 0; i < NumberOfEventsRead; ++i)
{
if (pCur[i].EventType == KEY_EVENT){
KEY_EVENT_RECORD KeyEvent = pCur[i].Event.KeyEvent;
if (KeyEvent.bKeyDown)printf ("Down\t"); else printf ("Up\t");
if (pCur[i].Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE) break;
_tprintf (_T("%c\n"), pCur[i].Event.KeyEvent.uChar.UnicodeChar);
}
}
pCur+= i;
if (i != NumberOfEventsRead) break;
} while (1);
return pCur - buf;
}
Слайд 19Операційні системи. Лекція 8. Кафедра ПІ. Качко О., Дягілєва Ф.
ekachko@gmail.com
ЗАПИС ДАНИХ В БУФЕР. ЧИТАННЯ З БУФЕРУ
int GetKeyEvents (HANDLE hin,
INPUT_RECORD *buf, int Count){
DWORD Numbers;
BOOL b = WriteConsoleInput( hin,buf, Count, &Numbers);
int i;
for (i = 0; i < Numbers; ++i){
if (buf[i].EventType == KEY_EVENT){
KEY_EVENT_RECORD KeyEvent = buf[i].Event.KeyEvent;
if (KeyEvent.bKeyDown)printf ("Down\t"); else printf ("Up\t");
_tprintf (_T("%c\n"), buf[i].Event.KeyEvent.uChar.UnicodeChar);
}
}
return Numbers;
}
Слайд 20Операційні системи. Лекція 8. Кафедра ПІ. Качко О., Дягілєва Ф.
ekachko@gmail.com
БУФЕР ДЛЯ ЕКРАНУ. ВИЗНАЧЕННЯ
Що таке?
2-х мірний масив символів та їх
атрибутів, які визначають колір та яскравість.
Тип даних для символу:
typedef struct _CHAR_INFO {
union {
WCHAR UnicodeChar;
CHAR AsciiChar;
} Char;
WORD Attributes; } CHAR_INFO, *PCHAR_INFO;
Може бути декілька, тоді активний визначає зміст екрану.
Для чого?
Хочемо коректувати дані (атрибути), які виводяться програмою, до того, як ці дані будуть відображені на екрані.
Тільки для текстового режиму.
Слайд 21Операційні системи. Лекція 8. Кафедра ПІ. Качко О., Дягілєва Ф.
ekachko@gmail.com
БУФЕР ДЛЯ ЕКРАНУ. ІНФОРМАЦІЙНІ ФУНКЦІЇ
Інформація про буфер екрану. Читання
BOOL WINAPI
GetConsoleScreenBufferInfo( __in HANDLE hConsoleOutput, __out PCONSOLE_SCREEN_BUFFER_INFO lpConsoleScreenBufferInfo );
typedef struct _CONSOLE_SCREEN_BUFFER_INFO {
COORD dwSize; // X – col, Y – Lines (80*25)
COORD dwCursorPosition; // поточне положення курсору 0
WORD wAttributes; // Атрибути символів 7
SMALL_RECT srWindow; // Інформція в форматі SMALL_RECT (0,0, 79,24)
COORD dwMaximumWindowSize; } // максимальний розмір консольного вікна (80*25)
CONSOLE_SCREEN_BUFFER_INFO;
Інформація про буфер екрану. Формування
BOOL WINAPI SetConsoleWindowInfo( __in HANDLE hConsoleOutput, __in BOOL bAbsolute, __in const SMALL_RECT* lpConsoleWindow );
bAbsolute (TRUE) – координати вікна (srWindow) – абсолютні, інакше – відносні
Слайд 22Операційні системи. Лекція 8. Кафедра ПІ. Качко О., Дягілєва Ф.
ekachko@gmail.com
БУФЕР ДЛЯ ЕКРАНУ. ІНФОРМАЦІЙНІ ФУНКЦІЇ. ПРИКЛАД
HANDLE hout = GetStdHandle (STD_OUTPUT_HANDLE);
if
(hout != INVALID_HANDLE_VALUE){
CONSOLE_SCREEN_BUFFER_INFO CSBInfo;
bRes = GetConsoleScreenBufferInfo( hout, &CSBInfo );
printf ("CSBInfo.dwCursorPosition = %d\n", CSBInfo.dwCursorPosition); // 0
printf ("CSBInfo.dwMaximumWindowSize.X = %d\n", CSBInfo.dwMaximumWindowSize.X);
printf ("CSBInfo.dwMaximumWindowSize.Y = %d\n", CSBInfo.dwMaximumWindowSize.Y); // 80, 25
printf ("CSBInfo.dwSize.X = %d\n", CSBInfo.dwSize.X);
printf ("CSBInfo.dwSize.Y = %d\n", CSBInfo.dwSize.Y); // 80, 25
printf ("CSBInfo.srWindow.Bottom = %d\n", CSBInfo.srWindow.Bottom);
printf ("CSBInfo.srWindow.Left = %d\n", CSBInfo.srWindow.Left); //24, 0
printf ("CSBInfo.srWindow.Right = %d\n", CSBInfo.srWindow.Right);
printf ("CSBInfo.srWindow.Top = %d\n", CSBInfo.srWindow.Top); // 79, 0
printf ("CSBInfo.wAttributes = %d\n", CSBInfo.wAttributes); // 7
}
Слайд 23Операційні системи. Лекція 8. Кафедра ПІ. Качко О., Дягілєва Ф.
ekachko@gmail.com
ВИСНОВКИ
1 Використання функцій WINAPI для роботи з файлами дозволяє суттєво
збільшити можливості, а саме:.
Можна використовувати імена файлів звичайні та довгі;
Можна задавати режими сувмісного доступу;
Можна задавати параметри безпеки.
2 Функція копіювання файлу дозволяє керувати режимами керування.
3. Розширена функція копіювання дозволяє відслідковувати процес копіювання.
4 Недолік – функції важкі в використанні
Слайд 24Операційні системи. Лекція 8. Кафедра ПІ. Качко О., Дягілєва Ф.
ekachko@gmail.com
ПИТАННЯ ДЛЯ САМОСТІЙНОГО ВИВЧЕННЯ
Вивчити потокові функції для роботи з файлами
(мова С++), порівняти продуктивність функцій С++ та WINAPI для великих файлів
Вивчити потокові функції для роботи з файлами (мова С#), порівняти продуктивність функцій С# та WINAPI для великих файлів
Слайд 25Операційні системи. Лекція 8. Кафедра ПІ. Качко О., Дягілєва Ф.
ekachko@gmail.com
МАТЕРІАЛИ ДЛЯ ЕКСПРЕС-КОНТРОЛЮ
Які параметри використовуються для завдання режими доступу до
файлів.(введення, виведення, введення та виведення)?
Які параметри використовуються для завдання режиму сумісного доступу до файлу?
Що буде, якщо для читання використовується не існуючій файл?
Що буде, якщо для запису використовується не існуючій файл??
Як прочитати вміст файлу, якщо його розмір невідомий?