398 lines
11 KiB
C
398 lines
11 KiB
C
|
|
#pragma once
|
|||
|
|
|
|||
|
|
#include <filesystem>
|
|||
|
|
#include <fostbite2D/types/type_alias.h>
|
|||
|
|
#include <optional>
|
|||
|
|
#include <string>
|
|||
|
|
#include <vector>
|
|||
|
|
|
|||
|
|
namespace frostbite2D {
|
|||
|
|
|
|||
|
|
namespace fs = std::filesystem;
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 文件信息结构体
|
|||
|
|
*/
|
|||
|
|
struct FileInfo {
|
|||
|
|
std::string name; ///< 文件名(包含扩展名)
|
|||
|
|
std::string extension; ///< 文件扩展名(包含点,如 ".txt")
|
|||
|
|
std::string fullPath; ///< 完整路径
|
|||
|
|
uint64 size = 0; ///< 文件大小(字节)
|
|||
|
|
bool isDirectory = false; ///< 是否为目录
|
|||
|
|
bool isRegularFile = false; ///< 是否为普通文件
|
|||
|
|
bool exists = false; ///< 是否存在
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 资源管理类(单例)
|
|||
|
|
*
|
|||
|
|
* 提供文件读写、目录操作、路径处理等功能。
|
|||
|
|
* 支持设置工作目录,所有相对路径将基于工作目录解析。
|
|||
|
|
* 支持 UTF-8 编码的中文路径。
|
|||
|
|
*
|
|||
|
|
* @example
|
|||
|
|
* auto& asset = Asset::get();
|
|||
|
|
* asset.setWorkingDirectory("D:/游戏/资源");
|
|||
|
|
* std::string content;
|
|||
|
|
* asset.readTextFile("配置/设置.json", content);
|
|||
|
|
*/
|
|||
|
|
class Asset {
|
|||
|
|
public:
|
|||
|
|
/**
|
|||
|
|
* @brief 获取单例实例
|
|||
|
|
* @return 资源管理器实例引用
|
|||
|
|
*/
|
|||
|
|
static Asset &get();
|
|||
|
|
|
|||
|
|
Asset(const Asset &) = delete;
|
|||
|
|
Asset &operator=(const Asset &) = delete;
|
|||
|
|
|
|||
|
|
// ---------------------------------------------------------------------------
|
|||
|
|
// 文件读写
|
|||
|
|
// ---------------------------------------------------------------------------
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 读取文本文件
|
|||
|
|
* @param path 文件路径(相对或绝对路径)
|
|||
|
|
* @param outContent 输出文件内容
|
|||
|
|
* @return 读取成功返回 true
|
|||
|
|
*/
|
|||
|
|
bool readTextFile(const std::string &path, std::string &outContent);
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 写入文本文件
|
|||
|
|
* @param path 文件路径
|
|||
|
|
* @param content 要写入的内容
|
|||
|
|
* @param append 是否追加模式,默认覆盖
|
|||
|
|
* @return 写入成功返回 true
|
|||
|
|
*/
|
|||
|
|
bool writeTextFile(const std::string &path, const std::string &content,
|
|||
|
|
bool append = false);
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 读取二进制文件
|
|||
|
|
* @param path 文件路径
|
|||
|
|
* @param outData 输出字节数组
|
|||
|
|
* @return 读取成功返回 true
|
|||
|
|
*/
|
|||
|
|
bool readBinaryFile(const std::string &path, std::vector<uint8> &outData);
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 写入二进制文件
|
|||
|
|
* @param path 文件路径
|
|||
|
|
* @param data 要写入的字节数组
|
|||
|
|
* @param append 是否追加模式,默认覆盖
|
|||
|
|
* @return 写入成功返回 true
|
|||
|
|
*/
|
|||
|
|
bool writeBinaryFile(const std::string &path, const std::vector<uint8> &data,
|
|||
|
|
bool append = false);
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 读取文本文件到字符串(便捷方法)
|
|||
|
|
* @param path 文件路径
|
|||
|
|
* @return 文件内容,失败返回 std::nullopt
|
|||
|
|
*/
|
|||
|
|
std::optional<std::string> readFileToString(const std::string &path);
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 读取二进制文件到字节数组(便捷方法)
|
|||
|
|
* @param path 文件路径
|
|||
|
|
* @return 字节数组,失败返回 std::nullopt
|
|||
|
|
*/
|
|||
|
|
std::optional<std::vector<uint8>> readFileToBytes(const std::string &path);
|
|||
|
|
|
|||
|
|
// ---------------------------------------------------------------------------
|
|||
|
|
// 文件/目录检查
|
|||
|
|
// ---------------------------------------------------------------------------
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 检查路径是否存在
|
|||
|
|
* @param path 路径
|
|||
|
|
* @return 存在返回 true
|
|||
|
|
*/
|
|||
|
|
bool exists(const std::string &path) const;
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 检查路径是否为目录
|
|||
|
|
* @param path 路径
|
|||
|
|
* @return 是目录返回 true
|
|||
|
|
*/
|
|||
|
|
bool isDirectory(const std::string &path) const;
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 检查路径是否为普通文件
|
|||
|
|
* @param path 路径
|
|||
|
|
* @return 是普通文件返回 true
|
|||
|
|
*/
|
|||
|
|
bool isRegularFile(const std::string &path) const;
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 检查文件或目录是否为空
|
|||
|
|
* @param path 路径
|
|||
|
|
* @return 为空返回 true
|
|||
|
|
*/
|
|||
|
|
bool isEmpty(const std::string &path) const;
|
|||
|
|
|
|||
|
|
// ---------------------------------------------------------------------------
|
|||
|
|
// 目录操作
|
|||
|
|
// ---------------------------------------------------------------------------
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 创建单层目录
|
|||
|
|
* @param path 目录路径
|
|||
|
|
* @return 创建成功返回 true
|
|||
|
|
*/
|
|||
|
|
bool createDirectory(const std::string &path);
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 递归创建多层目录
|
|||
|
|
* @param path 目录路径
|
|||
|
|
* @return 创建成功返回 true
|
|||
|
|
*/
|
|||
|
|
bool createDirectories(const std::string &path);
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 删除文件
|
|||
|
|
* @param path 文件路径
|
|||
|
|
* @return 删除成功返回 true
|
|||
|
|
*/
|
|||
|
|
bool removeFile(const std::string &path);
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 删除目录及其所有内容
|
|||
|
|
* @param path 目录路径
|
|||
|
|
* @return 删除成功返回 true
|
|||
|
|
*/
|
|||
|
|
bool removeDirectory(const std::string &path);
|
|||
|
|
|
|||
|
|
// ---------------------------------------------------------------------------
|
|||
|
|
// 文件操作
|
|||
|
|
// ---------------------------------------------------------------------------
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 复制文件
|
|||
|
|
* @param from 源文件路径
|
|||
|
|
* @param to 目标文件路径
|
|||
|
|
* @param overwrite 是否覆盖已存在的文件
|
|||
|
|
* @return 复制成功返回 true
|
|||
|
|
*/
|
|||
|
|
bool copyFile(const std::string &from, const std::string &to,
|
|||
|
|
bool overwrite = false);
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 移动文件
|
|||
|
|
* @param from 源文件路径
|
|||
|
|
* @param to 目标文件路径
|
|||
|
|
* @return 移动成功返回 true
|
|||
|
|
*/
|
|||
|
|
bool moveFile(const std::string &from, const std::string &to);
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 重命名文件或目录
|
|||
|
|
* @param oldPath 原路径
|
|||
|
|
* @param newPath 新路径
|
|||
|
|
* @return 重命名成功返回 true
|
|||
|
|
*/
|
|||
|
|
bool rename(const std::string &oldPath, const std::string &newPath);
|
|||
|
|
|
|||
|
|
// ---------------------------------------------------------------------------
|
|||
|
|
// 目录遍历
|
|||
|
|
// ---------------------------------------------------------------------------
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 列出目录中的所有文件
|
|||
|
|
* @param directoryPath 目录路径
|
|||
|
|
* @param recursive 是否递归遍历子目录
|
|||
|
|
* @return 文件路径列表
|
|||
|
|
*/
|
|||
|
|
std::vector<std::string> listFiles(const std::string &directoryPath,
|
|||
|
|
bool recursive = false);
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 列出目录中的所有子目录
|
|||
|
|
* @param directoryPath 目录路径
|
|||
|
|
* @param recursive 是否递归遍历子目录
|
|||
|
|
* @return 子目录路径列表
|
|||
|
|
*/
|
|||
|
|
std::vector<std::string> listDirectories(const std::string &directoryPath,
|
|||
|
|
bool recursive = false);
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 列出目录中的所有文件和子目录
|
|||
|
|
* @param directoryPath 目录路径
|
|||
|
|
* @param recursive 是否递归遍历子目录
|
|||
|
|
* @return 所有项目路径列表
|
|||
|
|
*/
|
|||
|
|
std::vector<std::string> listAll(const std::string &directoryPath,
|
|||
|
|
bool recursive = false);
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 按扩展名列出文件
|
|||
|
|
* @param directoryPath 目录路径
|
|||
|
|
* @param extension 文件扩展名(如 ".png")
|
|||
|
|
* @param recursive 是否递归遍历子目录
|
|||
|
|
* @return 匹配的文件路径列表
|
|||
|
|
*/
|
|||
|
|
std::vector<std::string>
|
|||
|
|
listFilesWithExtension(const std::string &directoryPath,
|
|||
|
|
const std::string &extension, bool recursive = false);
|
|||
|
|
|
|||
|
|
// ---------------------------------------------------------------------------
|
|||
|
|
// 文件信息
|
|||
|
|
// ---------------------------------------------------------------------------
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 获取文件详细信息
|
|||
|
|
* @param path 文件路径
|
|||
|
|
* @return 文件信息结构体
|
|||
|
|
*/
|
|||
|
|
FileInfo getFileInfo(const std::string &path);
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 获取文件大小
|
|||
|
|
* @param path 文件路径
|
|||
|
|
* @return 文件大小(字节)
|
|||
|
|
*/
|
|||
|
|
uint64 getFileSize(const std::string &path) const;
|
|||
|
|
|
|||
|
|
// ---------------------------------------------------------------------------
|
|||
|
|
// 路径处理
|
|||
|
|
// ---------------------------------------------------------------------------
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 获取文件名(包含扩展名)
|
|||
|
|
* @param path 文件路径
|
|||
|
|
* @return 文件名
|
|||
|
|
*/
|
|||
|
|
std::string getFileName(const std::string &path) const;
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 获取文件名(不含扩展名)
|
|||
|
|
* @param path 文件路径
|
|||
|
|
* @return 文件名
|
|||
|
|
*/
|
|||
|
|
std::string getFileNameWithoutExtension(const std::string &path) const;
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 获取文件扩展名
|
|||
|
|
* @param path 文件路径
|
|||
|
|
* @return 扩展名(包含点,如 ".txt")
|
|||
|
|
*/
|
|||
|
|
std::string getExtension(const std::string &path) const;
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 获取父目录路径
|
|||
|
|
* @param path 文件路径
|
|||
|
|
* @return 父目录路径
|
|||
|
|
*/
|
|||
|
|
std::string getParentPath(const std::string &path) const;
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 获取绝对路径
|
|||
|
|
* @param path 相对或绝对路径
|
|||
|
|
* @return 绝对路径
|
|||
|
|
*/
|
|||
|
|
std::string getAbsolutePath(const std::string &path) const;
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 获取规范路径(解析符号链接和相对路径)
|
|||
|
|
* @param path 路径
|
|||
|
|
* @return 规范化路径
|
|||
|
|
*/
|
|||
|
|
std::string getCanonicalPath(const std::string &path) const;
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 合并两个路径
|
|||
|
|
* @param left 左侧路径
|
|||
|
|
* @param right 右侧路径
|
|||
|
|
* @return 合并后的路径
|
|||
|
|
*/
|
|||
|
|
std::string combinePath(const std::string &left,
|
|||
|
|
const std::string &right) const;
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 规范化路径(转换为系统首选格式)
|
|||
|
|
* @param path 路径
|
|||
|
|
* @return 规范化路径
|
|||
|
|
*/
|
|||
|
|
std::string normalizePath(const std::string &path) const;
|
|||
|
|
|
|||
|
|
// ---------------------------------------------------------------------------
|
|||
|
|
// 工作目录
|
|||
|
|
// ---------------------------------------------------------------------------
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 获取当前工作目录
|
|||
|
|
* @return 当前工作目录路径
|
|||
|
|
*/
|
|||
|
|
std::string getCurrentPath() const;
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 设置当前工作目录
|
|||
|
|
* @param path 目录路径
|
|||
|
|
* @return 设置成功返回 true
|
|||
|
|
*/
|
|||
|
|
bool setCurrentPath(const std::string &path);
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 设置资源工作目录
|
|||
|
|
*
|
|||
|
|
* 设置后,所有相对路径操作都将基于此目录。
|
|||
|
|
*
|
|||
|
|
* @param path 工作目录路径
|
|||
|
|
*/
|
|||
|
|
void setWorkingDirectory(const std::string &path);
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 获取资源工作目录
|
|||
|
|
* @return 工作目录路径
|
|||
|
|
*/
|
|||
|
|
const std::string &getWorkingDirectory() const;
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 解析相对路径为完整路径
|
|||
|
|
* @param relativePath 相对路径
|
|||
|
|
* @return 完整路径
|
|||
|
|
*/
|
|||
|
|
std::string resolvePath(const std::string &relativePath) const;
|
|||
|
|
|
|||
|
|
// ---------------------------------------------------------------------------
|
|||
|
|
// 资源根目录
|
|||
|
|
// ---------------------------------------------------------------------------
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 设置资源根目录
|
|||
|
|
* @param root 资源根目录路径
|
|||
|
|
*/
|
|||
|
|
void setAssetRoot(const std::string &root);
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 获取资源根目录
|
|||
|
|
* @return 资源根目录路径
|
|||
|
|
*/
|
|||
|
|
const std::string &getAssetRoot() const;
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 解析资源相对路径
|
|||
|
|
*
|
|||
|
|
* 将相对路径解析为:工作目录/资源根目录/相对路径
|
|||
|
|
*
|
|||
|
|
* @param relativePath 相对路径
|
|||
|
|
* @return 完整路径
|
|||
|
|
*/
|
|||
|
|
std::string resolveAssetPath(const std::string &relativePath) const;
|
|||
|
|
|
|||
|
|
private:
|
|||
|
|
Asset() = default;
|
|||
|
|
~Asset() = default;
|
|||
|
|
|
|||
|
|
fs::path toPath(const std::string &path) const;
|
|||
|
|
std::string fromPath(const fs::path &path) const;
|
|||
|
|
std::string resolveFullPath(const std::string &path) const;
|
|||
|
|
|
|||
|
|
std::string workingDirectory_;
|
|||
|
|
std::string assetRoot_;
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
} // namespace frostbite2D
|