C++ Code Snippet -- 常用文件操作

128 阅读2分钟

对文件和文件夹的操作是日常开发中比较高频的操作,这里简单罗列几种高频的使用方法,如文件是否存在、级联创建文件夹、文件大小等等


#include <fstream>
#include <sys/stat.h>
#include <dirent.h>
#include "FileUtils.h"

/**
 * 判断文件是否存在
 */
bool FileUtils::isExist(const std::string &path) {
    std::ifstream is(path);
    bool isGood = is.good();
    is.close();
    return isGood;
}

/**
 * 获取一个路径的父目录
 */
std::string FileUtils::parentPath(const std::string &path) {
    auto position = path.find_last_of('/');

    // 找不到分隔符,返回空
    if (position == std::string::npos) {
        return "";
    }

    // 去掉最后一个'/'之后的其他字符
    auto temp = path.substr(0, position);

    // 如果最后一个字符是'/',去掉'/'后再找
    if (position == path.size() - 1) {
        return parentPath(temp);
    }

    return temp;
}

/**
 * 级联创建文件夹目录
 */
bool FileUtils::createDirectory(const std::string &path) {
    if (isExist(path)) {
        return true;
    }

    if (path.empty()) {
        return false;
    }

    // 逐级判断父目录是否存在,不存在创建父目录
    auto parent = parentPath(path);
    if (!isExist(parent)) {
        if (!createDirectory(parent)) {
            return false;
        }
    }

    int code = mkdir(path.c_str(), 0777);
    return (code == 0);
}

/**
 * 获取文件大小,字节数
 */
int FileUtils::getFileSize(std::string path) {
#ifdef UNIX
    struct stat buf;//文件字节数
        int res = stat(path.c_str(), &buf);
        if (res != 0) {
            return 0;
        } else {
            return buf.st_size;
        }
#elif WIN32
    struct _stat info;
        if(_stat(path.c_str(), &info) == 0)
        {
            return info.st_size;
        }
#endif
    return 0;
}

/**
 * 删除一个文件。
 */
bool FileUtils::deleteFile(const std::string &path) {
    if (!isExist(path)) {
        return true;
    }

    int code = remove(path.c_str());
    return (code == 0);
}

/**
 * 获取文件的名称
 * @param path 文件路径
 * @return
 */
std::string FileUtils::getFileName(const std::string &path) {
    if (path.empty()) {
        return "";
    }

    auto position = path.find_last_of('/');

    // 找不到分隔符,返回空
    if (position == std::string::npos) {
        return path;
    }

    // 路径的最后一个字符就是 '/'
    if (position == path.size() - 1) {
        return "";
    }

    // 最后一个'/' 之后的所有字符
    auto temp = path.substr(position + 1);

    return temp;
}

/**
 * 判断路径是否为一个文件夹
 */
bool FileUtils::isDirectory(const std::string &path) {
    if (!isExist(path)) {
        return false;
    }

    struct stat buffer{};
    int code = stat(path.c_str(), &buffer);
    if (code != 0) {
        return false;
    }
    bool isDir = S_ISDIR(buffer.st_mode);
    return isDir;
}

/**
 * 获取子文件夹目录
 */
std::vector<std::string> FileUtils::getSubFiles(const std::string &directory, bool returnAbsolutePath) {
    std::vector<std::string> res;
    if (!isDirectory(directory)) {
        return res;
    }

    struct dirent *ptr;
    DIR *dir = opendir(directory.c_str());

    while ((ptr = readdir(dir)) != nullptr) {
        std::string name = ptr->d_name;
        if (name == std::string(".") || name == std::string("..")) {
            continue;
        }
        if (returnAbsolutePath) {
            res.emplace_back(join(directory, name));
        } else {
            res.emplace_back(name);
        }
    }

    closedir(dir);

    return res;
}

/**
 * 拼接路径
 */
std::string FileUtils::join(const std::string &parent, const std::string &name) {
    if (parent.empty()) {
        return name;
    }

    auto size = parent.size();
    char lastChar = parent.at(size - 1);
    char firstChar = name.at(0);

    // 两个都没有 '/'
    if (lastChar != '/' && firstChar != '/') {
        return parent + "/" + name;
    }
        // 有一个 '/'
    else if (lastChar == '/' || firstChar == '/') {
        return parent + name;
    }
        // 有两个 '/'
    else {
        return parent + name.substr(1);
    }
}