首先文件压缩类的实列采用的是单列模式
单例类模板
cpp
template <class T>
class Singleton {
private:
Singleton() = default;
public:
~Singleton() = default;
Singleton(const Singleton &) = delete;
Singleton &operator=(const Singleton &) = delete;
Singleton(const Singleton &&) = delete;
Singleton &operator=(Singleton &&) = delete;
static T *instance() {
static T instance = T();
return &instance;
}
friend T;
};
filehelper继承这个类然后友员声明,表示只有这一个实列并且允许模板类 Singleton<FileHelper> 访问 FileHelper 的私有成员(包括私有构造函数)。
cpp
class FileHelper : public QObject, public Singleton<FileHelper> {
Q_OBJECT
friend class Singleton<FileHelper>;
判断传入字符串是否是一个有效字符串函数
将传入的字符串用qurl::fromuserinput转换为qurl,返回是否有效。
cpp
static bool isValidUrl(const QString &input) {
QUrl const url = QUrl::fromUserInput(input);
return url.isValid();
}
获取当前系统的桌面绝对路径
cpp
Q_INVOKABLE static QString desktopPath() {
return QStandardPaths::writableLocation(QStandardPaths::DesktopLocation);
}
获取当前系统桌面的url
cpp
Q_INVOKABLE static QUrl desktop() {
return QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::DesktopLocation));
}
获取文件名函数
cpp
Q_INVOKABLE static QString getFileName(const QUrl &filePath) {
spdlog::debug("getFileName: {}", filePath.toLocalFile().toUtf8().data());
QFileInfo const file_info(filePath.toLocalFile());
if (!file_info.exists()) {
return "";
}
return file_info.fileName();
}
获取文件路径
cpp
Q_INVOKABLE static QString getFilePath(const QUrl &filePath) {
return filePath.toLocalFile();
}
获取文件大小
采用windows文件操作方式实现,其实我觉得没必要,用qt的实现更简单
cpp
static size_t fileSize(std::string_view path) noexcept {
HANDLE file_info = CreateFile(charToWchar(path).c_str(), GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, nullptr);
if (file_info == INVALID_HANDLE_VALUE)
return 0;
LARGE_INTEGER size;
if (!GetFileSizeEx(file_info, &size)) {
CloseHandle(file_info);
return 0;
}
CloseHandle(file_info);
return static_cast<size_t>(size.QuadPart);
}
cpp
Q_INVOKABLE static QString getFileSize(const QUrl &filePath) {
return getSize(filePath.toLocalFile());
}
Q_INVOKABLE static QString getSize(const QString &filePath) {
QFileInfo const file_info(filePath);
if (!file_info.exists() || file_info.isDir())
return {};
auto const size = file_info.size();
return CommonTool::fileSize(static_cast<uint64_t>(size));
}
这个功能函数说实话,如果是我只会有一个函数实现。
获取app路径
cpp
Q_INVOKABLE static QString getAppPath() {
return QCoreApplication::applicationDirPath();
}
生成不重名文件函数
cpp
Q_INVOKABLE static QString getUniqueFileName(const QString &filePath) {
return CommonTool::getUniqueFileName(filePath.toUtf8().data()).c_str();
}
检查文件是否存在
cpp
static bool fileExists(const std::string_view file_path) noexcept {
DWORD const attr = GetFileAttributes(charToWchar(file_path).c_str());
return (attr != INVALID_FILE_ATTRIBUTES);
}
创建不重名文件
cpp
static std::string getUniqueFileName(const std::string_view file_path) noexcept {
spdlog::debug("getUniqueFileName: {}", file_path);
if (!fileExists(file_path))
return std::string(file_path);
std::string base_name = getBaseName(file_path);
std::string const extension = '.' + getExtention(file_path);
std::string const dir_path = directory(file_path);
spdlog::debug("base_name: {}", base_name);
int count = 1;
std::string new_name = base_name + extension;
std::string new_path = dir_path + "/" + new_name;
spdlog::debug("new_path: {}", new_path);
bool exists = fileExists(new_path);
while (exists) {
new_name = base_name;
new_name += '(' + std::to_string(count) + ')' + extension;
new_path = dir_path + "/";
new_path += new_name;
spdlog::debug("new_path: {}", new_path);
count++;
exists = fileExists(new_path);
}
spdlog::debug("getUniqueFileName: {}", dir_path + "/" + new_name);
return dir_path + "/" + new_name;
}
cpp
Q_INVOKABLE static QString getUniqueFileName(const QString &filePath) {
return CommonTool::getUniqueFileName(filePath.toUtf8().data()).c_str();
}
获取文件名
cpp
static std::string getBaseName(std::string_view path) noexcept {
std::string const path_str(path);
size_t const pos_slash = path_str.find_last_of("\\/");
std::string file_name = (pos_slash != std::string::npos) ? path_str.substr(pos_slash + 1) : path_str;
size_t const pos_dot = file_name.find_last_of('.');
if (pos_dot != std::string::npos) {
file_name = file_name.substr(0, pos_dot);
}
return file_name;
}
就是找到/和.之间的文件名返回,采用的是c++的string_view,其实也可以用字符串的find操作或者qt的qfileinfo::basename一样可以实现。