Файловый менеджер на С++
Разработка файлового менеджера на C++ - это отличный способ углубить свои знания в области программирования, особенно в работе с файловой системой, обработке пользовательского ввода и создании графического интерфейса (если планируется GUI-версия). Файловый менеджер, по сути, является инструментом для навигации по файловой системе компьютера, позволяющим выполнять различные операции с файлами и директориями: создание, удаление, копирование, перемещение, переименование, просмотр свойств и т.д.
C++ предоставляет мощные средства для работы с файловой системой через стандартную библиотеку <filesystem> (начиная со стандарта C++17) и низкоуровневые API операционной системы (например, WinAPI для Windows или POSIX API для Linux/macOS). Выбор подхода зависит от требований к проекту:
- <filesystem> (C++17 и новее): Обеспечивает кроссплатформенность и более высокий уровень абстракции, что упрощает разработку и делает код более переносимым. Рекомендуется для большинства современных проектов.
- API операционной системы (WinAPI, POSIX): Предоставляет более полный контроль над файловой системой и доступ к специфическим функциям ОС, но делает код платформозависимым. Может потребоваться для задач, требующих максимальной производительности или доступа к низкоуровневым функциям.
В зависимости от того, какой интерфейс вы хотите реализовать, можно выделить два основных типа файловых менеджеров:
- консольные (CLI): Управление осуществляется через текстовые команды в командной строке или терминале. Проще в реализации, но менее удобны для пользователя.
- графические (GUI): Используют графический интерфейс пользователя (окна, кнопки, меню, списки файлов и т.д.). Более сложные в разработке, но обеспечивают интуитивно понятное управление.
В процессе разработки файлового менеджера на C++ вы столкнетесь с необходимостью решения следующих задач:
- получение списка файлов и директорий: Использование функций для чтения содержимого директорий.
- обработка путей к файлам: Работа с абсолютными и относительными путями, их нормализация и проверка корректности.
- операции с файлами и директориями: Реализация функций создания, удаления, копирования, перемещения и переименования файлов и директорий.
- обработка ошибок: Корректная обработка возможных ошибок при работе с файловой системой (например, отсутствие файла, недостаточно прав доступа и т.д.).
- пользовательский интерфейс (для GUI-версий): Создание и управление элементами графического интерфейса, обработка событий пользователя.
Далее мы рассмотрим пример простого консольного файлового менеджера написанного на С++20, используя модульность.
Если Вы используете VS2022 тогда создайте файл file_manager.ixx в других IDE возможно file_manager.cppm.
Этот файл содержит объявление интерфейса модуля file_manager. Здесь мы определяем класс FileManager и его методы.
export module file_manager; export import <string>; export import <vector>; export import <filesystem>; export class FileManager { public: // Конструктор, инициализирует файловый менеджер FileManager(); // Основной метод для отображения и взаимодействия с пользователем void display(); // Метод для создания файла void createFile(const std::string& filename); // Метод для удаления файла void deleteFile(const std::string& filename); // Метод для отображения списка файлов void listFiles(); // Метод для смены текущей директории void changeDirectory(const std::string& newDirectory); // Метод для смены текущего диска void changeDisk(); // Метод для отображения доступных логических дисков void listDisks(); private: // Текущая директория std::string currentDirectory; // Список файлов в текущей директории std::vector<std::string> files; // Метод для обновления списка файлов void refresh(); // Метод для очистки консоли void clearConsole(); };
Файл file_manager.cpp реализует методы класса FileManager, а также используется для управления вводом/выводом и работы с файловой системой.
module; #include <iostream> #include <fstream> #include <vector> #include <stdexcept> // Код, предназначенный для Windows #ifdef _WIN32 #include <windows.h> #endif module file_manager; namespace fs = std::filesystem; // Константы для ANSI кодов цветов const std::string RED = "\033[1;31m"; const std::string GREEN = "\033[1;32m"; const std::string YELLOW = "\033[1;33m"; const std::string RESET = "\033[0m"; // Конструктор класса FileManager, инициализирует текущий диск FileManager::FileManager() { // Отображаем доступные диски listDisks(); // Смена диска на указанный пользователем changeDisk(); } // Метод для обновления списка файлов в текущей директории void FileManager::refresh() { files.clear(); for (const auto& entry : fs::directory_iterator(currentDirectory)) { files.push_back(entry.path().filename().string()); } } // Метод для очистки консоли void FileManager::clearConsole() { // Код, предназначенный для Windows #ifdef _WIN32 std::system("cls"); #else // Код, предназначенный для других операционных систем (например, Unix-подобных) std::system("clear"); #endif } // Основной метод для отображения и взаимодействия с пользователем void FileManager::display() { char choice; std::string filename; std::string newDirectory; std::string newDisk; while (true) { std::cout << "\nФайловый менеджер — Текущий каталог:" << currentDirectory << "\n"; std::cout << "1. Список файлов\n"; std::cout << "2. Создать файл\n"; std::cout << "3. Удалить файл\n"; std::cout << "4. Изменить каталог\n"; std::cout << "5. Сменить диск\n"; std::cout << "6. Очистить консоль\n"; std::cout << "7. Выход\n"; std::cout << "Введите свой выбор: "; std::cin >> choice; switch (choice) { case '1': // Отображение списка файлов listFiles(); break; case '2': std::cout << "Введите имя файла для создания: "; std::cin >> filename; // Создание нового файла createFile(filename); break; case '3': std::cout << "Введите имя файла для удаления: "; std::cin >> filename; // Удаление указанного файла deleteFile(filename); break; case '4': std::cout << "Введите новый каталог: "; std::cin >> newDirectory; // Смена текущей директории changeDirectory(newDirectory); break; case '5': // Смена текущего диска changeDisk(); break; case '6': // Очистить консоль clearConsole(); break; case '7': // Выход из программы return; default: std::cout << RED << "Неверный выбор. Попробуйте еще раз." << RESET << "\n"; break; } } } // Метод для создания нового файла void FileManager::createFile(const std::string& filename) { // Создаём новый файл std::ofstream outfile(currentDirectory + "/" + filename); outfile.close(); refresh(); std::cout << GREEN << "Файл успешно создан." << RESET << "\n"; } // Метод для удаления файла void FileManager::deleteFile(const std::string& filename) { // Удаляем файл if (fs::remove(currentDirectory + "/" + filename)) { refresh(); std::cout << GREEN << "Файл успешно удален." << RESET << "\n"; } else { std::cout << RED << "Файл не найден." << RESET << "\n"; } } // Метод для отображения списка файлов в текущей директории void FileManager::listFiles() { std::cout << YELLOW << "\nФайлы в каталоге:\n" << RESET; for (const auto& file : files) { std::cout << YELLOW << "- " << file << RESET << "\n"; } } // Метод для смены текущей директории void FileManager::changeDirectory(const std::string& newDirectory) { // Проверяем, существует ли указанный путь и является ли он директорией if (fs::exists(newDirectory) && fs::is_directory(newDirectory)) { currentDirectory = newDirectory; refresh(); std::cout << GREEN << "Каталог изменен на " << currentDirectory << RESET << "\n"; } else { std::cout << RED << "Неверный каталог. Попробуйте еще раз."<< RESET << "\n"; } } // Метод для смены текущего диска void FileManager::changeDisk() { std::string rootPath; do { std::cout << "Введите диск для далнейшей работы (например, C:\\ или /): "; std::string disk; std::cin >> disk; // Создаем строку для хранения пути к корневой директории диска rootPath = disk; // Проверяем, заканчивается ли строка символом '/' или '\\' // Если нет, добавляем '/' в конец строки, чтобы путь был корректным if (disk.back() != '/' && disk.back() != '\\') { rootPath += "/"; } // Проверяем, существует ли указанный путь и является ли он директорией if (fs::exists(rootPath) && fs::is_directory(rootPath)) { // Если путь корректен, обновляем текущую директорию currentDirectory = rootPath; // Обновляем список файлов в текущей директории refresh(); std::cout << GREEN << "Диск изменен на " << disk << RESET << "\n"; } else { std::cout << RED << "Неверный диск. Попробуйте еще раз." << RESET << "\n"; } } while (!(fs::exists(rootPath) && fs::is_directory(rootPath))); } // Метод для отображения доступных логических дисков void FileManager::listDisks() { // Создаем вектор для хранения списка доступных логических дисков std::vector<std::string> disks; #ifdef _WIN32 // Буфер для хранения имен дисков char buffer[256]; // Для Windows используем GetLogicalDriveStringsA для получения строки с именами логических дисков // Получаем строку с именами логических дисков DWORD result = GetLogicalDriveStringsA(sizeof(buffer) - 1, buffer); // Проверяем, успешно ли выполнена операция и помещаем имена дисков в вектор if (result > 0 && result <= sizeof(buffer)) { char* drive = buffer; // Перебираем все логические диски в буфере while (*drive) { // Добавляем имя диска в вектор disks.push_back(drive); // Переходим к следующему диску в строке drive += strlen(drive) + 1; } } #else // Для Unix-подобных систем добавляем корневой каталог в список дисков disks.push_back("/"); #endif // Выводим список доступных логических дисков на экран std::cout << YELLOW << "Доступные диски:\n"; for (const auto& disk : disks) { std::cout << "- " << disk << "\n"; } std::cout << RESET; }
Файл main.cpp содержит основную функцию программы, которая создает объект файлового менеджера и запускает его основной метод display.
#include <iostream> import file_manager; int main() { system("chcp 1251>nul"); FileManager fm; fm.display(); return 0; }
Результат работы данной программы.