Files
Bionic_sphere/Bionic_Core/ToolsClass/SDFileManager/SDFileManager.cpp
T
Misaki 97fe13da26 1. 完成了对音频播放类的完整C++封装,测试通过
2. 修复了LVGL渲染类当中的一些小bug
3. 增加了一些CPU资源占用的日志打印函数,运行在主线程当中
4. 完善了底层通信类的封装,基于websocket,尚未测试
2025-09-12 02:11:50 +08:00

511 lines
14 KiB
C++

//
// Created by misaki on 2025/9/9.
//
#include "SDFileManager.h"
#include "SD_MMC.h"
#include <cstring>
#include <vector>
#include <string>
#include <iomanip>
SDFileManager* SDFileManager::SDFileInstance = nullptr;
std::mutex SDFileManager::instance_mutex;
SDFileManager *SDFileManager::getInstance() {
// 双检锁(DCLP),C++11 起 atomic+mutex 组合保证线程安全
SDFileManager* tmp = SDFileInstance;
if (tmp == nullptr) {
std::lock_guard<std::mutex> lock(instance_mutex);
tmp = SDFileInstance;
if (tmp == nullptr) {
tmp = new SDFileManager();
SDFileInstance = tmp;
}
}
return tmp;
}
SDFileManager::SDFileManager() : is_initialized(false), current_directory(MOUNT_POINT) {
// 初始化SD卡
init();
// 获取Flash大小
Flash_Searching();
}
SDFileManager::~SDFileManager() {
// 清理资源
}
void SDFileManager::init() {
SD_Init();
is_initialized = true;
}
void SDFileManager::tryInitSDCard() {
ESP_LOGI("SDFileManager", "Trying to initialize SD card...");
}
bool SDFileManager::writeFileSync(const char* path, const char* data) {
std::lock_guard<std::mutex> lock(file_operation_mutex);
if (!is_initialized) {
ESP_LOGE("SDFileManager", "SD card not initialized");
return false;
}
esp_err_t result = s_example_write_file(path, const_cast<char*>(data));
return result == ESP_OK;
}
std::string SDFileManager::readFileSync(const char* path) {
std::lock_guard<std::mutex> lock(file_operation_mutex);
if (!is_initialized) {
ESP_LOGE("SDFileManager", "SD card not initialized");
return "";
}
FILE* file = fopen(path, "r");
if (file == nullptr) {
ESP_LOGE("SDFileManager", "Failed to open file: %s", path);
return "";
}
// 获取文件大小
fseek(file, 0, SEEK_END);
long size = ftell(file);
fseek(file, 0, SEEK_SET);
// 读取文件内容
std::string content;
content.resize(size);
size_t bytes_read = fread(&content[0], 1, size, file);
fclose(file);
if (bytes_read != static_cast<size_t>(size)) {
ESP_LOGE("SDFileManager", "Failed to read entire file: %s", path);
return "";
}
return content;
}
std::vector<std::string> SDFileManager::listFilesSync(const char* directory, const char* extension) {
std::lock_guard<std::mutex> lock(file_operation_mutex);
if (!is_initialized) {
ESP_LOGE("SDFileManager", "SD card not initialized");
return {};
}
const int max_files = 50;
char file_names[max_files][100];
uint16_t file_count = Folder_retrieval(directory, extension, file_names, max_files);
std::vector<std::string> files;
for (uint16_t i = 0; i < file_count; ++i) {
files.emplace_back(file_names[i]);
}
return files;
}
FILE* SDFileManager::openFileSync(const char* path, const char* mode) {
std::lock_guard<std::mutex> lock(file_operation_mutex);
if (!is_initialized) {
ESP_LOGE("SDFileManager", "SD card not initialized");
return nullptr;
}
return Open_File(path);
}
bool SDFileManager::closeFileSync(FILE* file) {
if (file != nullptr) {
return fclose(file) == 0;
}
return false;
}
void SDFileManager::asyncWriteFile(const char* path, const char* data, WriteCallback callback) {
ThreadConfig config = getThreadConfig("write_file");
ThreadManager::createThread(config, [this, path = std::string(path),
data = std::string(data), callback]() {
bool success = this->writeFileSync(path.c_str(), data.c_str());
if (callback) {
callback(success, path.c_str());
}
}).detach(); // 分离线程,使其独立运行
}
void SDFileManager::asyncReadFile(const char* path, ReadCallback callback) {
if (!callback) {
return; // 没有回调函数,异步读取无意义
}
ThreadConfig config = getThreadConfig("read_file");
ThreadManager::createThread(config, [this, path = std::string(path), callback]() {
std::string content = this->readFileSync(path.c_str());
bool success = !content.empty();
callback(success, path.c_str(), content);
}).detach();
}
void SDFileManager::asyncListFiles(const char* directory, const char* extension, ListCallback callback) {
if (!callback) {
return; // 没有回调函数,异步列出文件无意义
}
ThreadConfig config = getThreadConfig("list_files");
ThreadManager::createThread(config, [this, directory = std::string(directory),
extension = std::string(extension ? extension : ""),
callback]() {
std::vector<std::string> files = this->listFilesSync(
directory.c_str(),
extension.empty() ? nullptr : extension.c_str()
);
bool success = !files.empty();
callback(success, files);
}).detach();
}
void SDFileManager::asyncOpenFile(const char* path, const char* mode, OpenCallback callback) {
if (!callback) {
return; // 没有回调函数,异步打开文件无意义
}
ThreadConfig config = getThreadConfig("open_file");
ThreadManager::createThread(config, [this, path = std::string(path),
mode = std::string(mode), callback]() {
FILE* file = this->openFileSync(path.c_str(), mode.c_str());
bool success = (file != nullptr);
callback(success, file);
}).detach();
}
ThreadConfig SDFileManager::getThreadConfig(const char* operation) {
ThreadConfig config;
config.name = "sd_" + std::string(operation);
config.core_id = -1; // 不绑定核心
config.stack_size = 4096;
config.priority = 5;
config.inherit_cfg = false;
return config;
}
// 实现ls命令
std::string SDFileManager::lsCommand(const char* path, bool recursive, bool showDetails) {
std::lock_guard<std::mutex> lock(file_operation_mutex);
if (!is_initialized) {
ESP_LOGE("SDFileManager", "SD card not initialized");
return "Error: SD card not initialized";
}
std::string fullPath = path;
if (fullPath.empty() || fullPath == ".") {
fullPath = current_directory;
} else if (fullPath[0] != '/') {
// 相对路径
fullPath = current_directory + "/" + fullPath;
}
DIR* dir = opendir(fullPath.c_str());
if (dir == nullptr) {
return "Error: Cannot open directory " + fullPath;
}
std::stringstream result;
struct dirent* entry;
struct stat st;
result << "Directory listing for: " << fullPath << "\n";
result << "----------------------------------------\n";
while ((entry = readdir(dir)) != nullptr) {
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) {
continue;
}
std::string entryPath = fullPath + "/" + entry->d_name;
if (stat(entryPath.c_str(), &st) != 0) {
continue;
}
if (showDetails) {
result << getFileInfoString(entry->d_name, &st);
} else {
result << entry->d_name;
}
if (S_ISDIR(st.st_mode)) {
result << "/";
}
result << "\n";
// 递归列出子目录
if (recursive && S_ISDIR(st.st_mode)) {
std::string subDirResult = lsCommand(entryPath.c_str(), true, showDetails);
result << subDirResult;
}
}
closedir(dir);
return result.str();
}
// 实现cat命令
std::string SDFileManager::catCommand(const char* path, bool lineNumbers) {
std::lock_guard<std::mutex> lock(file_operation_mutex);
if (!is_initialized) {
ESP_LOGE("SDFileManager", "SD card not initialized");
return "Error: SD card not initialized";
}
std::string fullPath = path;
if (fullPath[0] != '/') {
// 相对路径
fullPath = current_directory + "/" + fullPath;
}
FILE* file = fopen(fullPath.c_str(), "r");
if (file == nullptr) {
return "Error: Cannot open file " + fullPath;
}
std::stringstream result;
char buffer[256];
int lineNumber = 1;
while (fgets(buffer, sizeof(buffer), file) != nullptr) {
if (lineNumbers) {
result << std::setw(4) << lineNumber << ": ";
}
result << buffer;
lineNumber++;
}
fclose(file);
return result.str();
}
// 实现pwd命令
std::string SDFileManager::pwdCommand() {
return current_directory;
}
// 实现cd命令
bool SDFileManager::cdCommand(const char* path) {
std::lock_guard<std::mutex> lock(file_operation_mutex);
if (!is_initialized) {
ESP_LOGE("SDFileManager", "SD card not initialized");
return false;
}
std::string newPath;
if (path[0] == '/') {
// 绝对路径
newPath = path;
} else if (strcmp(path, "..") == 0) {
// 上级目录
size_t pos = current_directory.find_last_of('/');
if (pos != std::string::npos && pos > 0) {
newPath = current_directory.substr(0, pos);
} else {
newPath = "/";
}
} else {
// 相对路径
newPath = current_directory + "/" + path;
}
// 检查路径是否存在且是目录
struct stat st;
if (stat(newPath.c_str(), &st) != 0 || !S_ISDIR(st.st_mode)) {
return false;
}
current_directory = newPath;
return true;
}
// 实现mkdir命令
bool SDFileManager::mkdirCommand(const char* path) {
std::lock_guard<std::mutex> lock(file_operation_mutex);
if (!is_initialized) {
ESP_LOGE("SDFileManager", "SD card not initialized");
return false;
}
std::string fullPath = path;
if (fullPath[0] != '/') {
// 相对路径
fullPath = current_directory + "/" + fullPath;
}
// 创建目录
int result = mkdir(fullPath.c_str(), 0777);
return result == 0;
}
// 实现rm命令
bool SDFileManager::rmCommand(const char* path, bool recursive) {
std::lock_guard<std::mutex> lock(file_operation_mutex);
if (!is_initialized) {
ESP_LOGE("SDFileManager", "SD card not initialized");
return false;
}
std::string fullPath = path;
if (fullPath[0] != '/') {
// 相对路径
fullPath = current_directory + "/" + fullPath;
}
struct stat st;
if (stat(fullPath.c_str(), &st) != 0) {
return false;
}
if (S_ISDIR(st.st_mode)) {
if (recursive) {
return removeDirectoryRecursive(fullPath.c_str());
} else {
// 非递归删除空目录
return rmdir(fullPath.c_str()) == 0;
}
} else {
// 删除文件
return remove(fullPath.c_str()) == 0;
}
}
// 实现stat命令
std::string SDFileManager::statCommand(const char* path) {
std::lock_guard<std::mutex> lock(file_operation_mutex);
if (!is_initialized) {
ESP_LOGE("SDFileManager", "SD card not initialized");
return "Error: SD card not initialized";
}
std::string fullPath = path;
if (fullPath[0] != '/') {
// 相对路径
fullPath = current_directory + "/" + fullPath;
}
struct stat st;
if (stat(fullPath.c_str(), &st) != 0) {
return "Error: Cannot get file status for " + fullPath;
}
return getFileInfoString(fullPath.c_str(), &st);
}
// 辅助方法:递归删除目录
bool SDFileManager::removeDirectoryRecursive(const char* path) {
DIR* dir = opendir(path);
if (dir == nullptr) {
return false;
}
struct dirent* entry;
while ((entry = readdir(dir)) != nullptr) {
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) {
continue;
}
std::string entryPath = std::string(path) + "/" + entry->d_name;
struct stat st;
if (stat(entryPath.c_str(), &st) != 0) {
continue;
}
if (S_ISDIR(st.st_mode)) {
if (!removeDirectoryRecursive(entryPath.c_str())) {
closedir(dir);
return false;
}
} else {
if (remove(entryPath.c_str()) != 0) {
closedir(dir);
return false;
}
}
}
closedir(dir);
return rmdir(path) == 0;
}
// 辅助方法:获取文件信息字符串
std::string SDFileManager::getFileInfoString(const char* path, const struct stat* st) {
std::stringstream info;
// 文件类型和权限
info << getFileTypeString(st->st_mode);
info << ((st->st_mode & S_IRUSR) ? "r" : "-");
info << ((st->st_mode & S_IWUSR) ? "w" : "-");
info << ((st->st_mode & S_IXUSR) ? "x" : "-");
info << ((st->st_mode & S_IRGRP) ? "r" : "-");
info << ((st->st_mode & S_IWGRP) ? "w" : "-");
info << ((st->st_mode & S_IXGRP) ? "x" : "-");
info << ((st->st_mode & S_IROTH) ? "r" : "-");
info << ((st->st_mode & S_IWOTH) ? "w" : "-");
info << ((st->st_mode & S_IXOTH) ? "x" : "-");
// 文件大小
info << " " << std::setw(10) << formatFileSize(st->st_size);
// 最后修改时间
struct tm* timeinfo = localtime(&st->st_mtime);
char timeBuf[20];
strftime(timeBuf, sizeof(timeBuf), "%Y-%m-%d %H:%M", timeinfo);
info << " " << timeBuf;
// 文件名
info << " " << path;
return info.str();
}
// 辅助方法:获取文件类型字符串
std::string SDFileManager::getFileTypeString(mode_t mode) {
if (S_ISREG(mode)) return "-"; // 普通文件
if (S_ISDIR(mode)) return "d"; // 目录
if (S_ISCHR(mode)) return "c"; // 字符设备
if (S_ISBLK(mode)) return "b"; // 块设备
if (S_ISFIFO(mode)) return "p"; // 管道
if (S_ISLNK(mode)) return "l"; // 符号链接
if (S_ISSOCK(mode)) return "s"; // 套接字
return "?"; // 未知类型
}
// 辅助方法:格式化文件大小
std::string SDFileManager::formatFileSize(size_t size) {
std::stringstream ss;
if (size < 1024) {
ss << size << " B";
} else if (size < 1024 * 1024) {
ss << std::fixed << std::setprecision(1) << (size / 1024.0) << " KB";
} else if (size < 1024 * 1024 * 1024) {
ss << std::fixed << std::setprecision(1) << (size / (1024.0 * 1024.0)) << " MB";
} else {
ss << std::fixed << std::setprecision(1) << (size / (1024.0 * 1024.0 * 1024.0)) << " GB";
}
return ss.str();
}