// #import "@local/nure:0.0.0": *
#import "lib.typ": *

#show: lab-pz-template.with(
  doctype: "ЛБ",
  title: "Керування зовнішніми пристроями. Нестандартні пристрої",
  subject_shorthand: "ОС",
  department_gen: "Програмної інженерії",
  authors: (
    (
      name: "Ситник Є. С.",
      full_name_gen: "Ситника Єгора Сергійовича",
      group: "ПЗПІ-23-2",
      gender: "m",
      variant: none,
    ),
    (
      name: "Малишкін А. С.",
      full_name_gen: "Малишкіна Андрія Сергійовича",
      group: "ПЗПІ-23-2",
      gender: "m",
      variant: none,
    ),
  ),
  mentor: (
    name: "Мельнікова Р. В.",
    gender: "f",
    degree: "доц. каф. ПІ",
  ),
  worknumber: 4,
)

#v(-spacing)

== Мета роботи
Навчитися практичному використанню функцій WinAPI для роботи з файлами.

== Хід роботи
#v(-spacing)
=== Створення класу для роботи з пристроями, файлами та каталогами.
#v(-spacing)
==== Вивчити усі функції, які використовуються для роботи з пристроями, файлами та каталогами в C\#.
В C\# класи для роботи з пристроями, файлами та каталогами знаходяться в просторі імен "System.IO".
Такі класи як "File", "FileStream", "Directory" та "DriveInfo" надають основні засоби для взаємодії з файловою системою.

Клас "File" пропонує статичні методи для виконання базових операцій над файлами.
До них належать: створення нового файлу ("File.Create"), видалення існуючого файлу ("File.Delete"),
перевірка існування файлу ("File.Exists"), копіювання файлу ("File.Copy"), переміщення файлу ("File.Move"), та інші.

Клас "FileStream" надає базову функціональність для роботи з файлами як з потоками даних.
Його основні функції включають відкриття файлу для читання або запису (через конструктори або методи "Open", "OpenRead", "OpenWrite"),
читання даних з файлу ("Read"), запис даних у файл ("Write"), закриття файлового потоку
("Close" або використання блоку "using" для автоматичного закриття), а також керування поточною позицією у файлі ("Seek").

Клас "Directory" надає статичні методи для виконання базових операцій над директоріями.
Серед них: створення нової директорії ("Directory.CreateDirectory"), видалення існуючої директорії ("Directory.Delete"),
перевірка існування директорії ("Directory.Exists"), переміщення директорії ("Directory.Move"),
а також отримання списку файлів у директорії ("Directory.GetFiles") та списку піддиректорій ("Directory.GetDirectories").

Клас "DriveInfo" надає інформацію про логічні диски, підключені до комп'ютера,
для отримання інформації про конкретний диск необхідно створити його екземпляр,
передавши ім'я диску в конструктор, а серед основних властивостей можна знайти ім'я диску ("Name"),
його тип ("DriveType"), стан готовності ("IsReady"), загальний розмір ("TotalSize"),
доступний вільний простір ("AvailableFreeSpace"), формат файлової системи ("DriveFormat"),
мітку тому ("VolumeLabel") та об'єкт кореневого каталогу ("RootDirectory"),
а для отримання інформації про всі диски в системі використовується статичний метод "GetDrives".

==== Визначити клас (класи) для мови С++, інтерфейс для яких подібний інтерфейсу C\#.
Створимо на C++ класи "File", "FileStream", "Directory" та "DriveInfo". Для кожного з них створимо власний файл заголовків.

#figure(image("img/File.h.png", width: 83%), caption: [Вміст файлу "File.h"])
#figure(image("img/FileStream.h.png", width: 83%), caption: [Вміст файлу "FileStream.h"])
#figure(image("img/Directory.h.png", width: 83%), caption: [Вміст файлу "Directory.h"])
#figure(image("img/DriveInfo.h.png", width: 96%), caption: [Вміст файлу "DriveInfo.h"])

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

Наприклад функція "SetAttributes" класу "File" має наступний вигляд:
#figure(image("img/File_SetAttributes.png"), caption: [Реалізація функції "SetAttributes" класу "File"])

Таким чином реалізовано більшість методів.

Із методів, що не мають точних аналогів у WinAPI можна виділити такі.

#figure(image("img/File_GetSize.png", width: 85%), caption: [Реалізація функції "GetSize" класу "File"])
#figure(
  image("img/Directory_GetDirectories.png", width: 85%),
  caption: [Реалізація функції "GetDirectories" класу "Directory"],
)
#figure(image("img/Directory_GetFiles.png"), caption: [Реалізація функції "GetFiles" класу "Directory"])
#figure(image("img/DriveInfo_GetDrives.png"), caption: [Реалізація функції "GetDrives" класу "DriveInfo"])

==== Порівняти швидкодію функцій при їх використанні для C\#, C в разі використання великих файлів.

Створимо прості програми для порівняння швидкодії функцій стандартної бібліотеки C\# та функцій реалізованих на С++.

Для замірів часу на С++ використаємо модуль "chrono" із стандартної бібліотеки.

Для зручності тестів заздалегідь підготуємо всі змінні із потрібними шляхами:
#figure(image("img/cpp_1.png"), caption: [Підготовка до тестів])

Додамо код для тестів:
#figure(image("img/cpp_2.png"), caption: [Тест запису в файл])
#figure(image("img/cpp_3.png"), caption: [Тест копіювання файлу])
#figure(image("img/cpp_4.png"), caption: [Тест читання з файлу])
#figure(image("img/cpp_5.png"), caption: [Тест отримання та встановлення атрибутів файлу])
#figure(image("img/cpp_6.png"), caption: [Тест переміщення файлу])
#figure(image("img/cpp_7.png"), caption: [Тест переміщення директорії])
#figure(image("img/cpp_8.png"), caption: [Тест отримання інформації про носії даних])

Для замірів часу на C\# скористаємося класом "StopWatch" стандартної бібліотеки.

Для зручності тестів заздалегідь підготуємо всі змінні із потрібними шляхами:
#figure(image("img/cs_1.png"), caption: [Підготовка до тестів])

Додамо код для тестів:
#figure(image("img/cs_2.png"), caption: [Тест запису в файл])
#figure(image("img/cs_3.png"), caption: [Тест копіювання файлу])
#figure(image("img/cs_4.png"), caption: [Тест читання з файлу])
#figure(image("img/cs_5.png"), caption: [Тест отримання та встановлення атрибутів файлу])
#figure(image("img/cs_6.png"), caption: [Тест переміщення файлу])
#figure(image("img/cs_7.png"), caption: [Тест переміщення директорії])
#figure(image("img/cs_8.png"), caption: [Тест отримання інформації про носії даних])

Запустимо обидві програми, та порівняємо результати.

// #figure(image("img/cpp_test.png"), caption: [Результат тестування С++ програми])
#figure(image("img/test.jpg", width: 87%), caption: [Результат тестування програм])

Варто зазначити, що оскільки лабораторна робота виконувалась на операційній системі Linux, програми показують дещо різні результати. Для запуску C++ версії було використано шар трансляції Wine, в той час коли C\# версія працює нативно, через це інформація про диски в C++ та C\# версії не співпадають.

Швидкодія обох версій відрізняється незначно, це можна пояснити тим, що обидві програми використовують системну API (WinAPI в випадку із Windows) для взаємодії із файловою системою.

== Висновки
Під час виконання даної лабораторної роботи ми навчилися практичному використанню функцій WinAPI для роботи з файлами.
