Файловый менеджер на С++
Разработка файлового менеджера на 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;
}
Результат работы данной программы.