陈小羊

导航

【转载】Linux C++ 实现文件目录常见操作(拷贝文件,拷贝目录,获取文件大小,获取目录大小,获取目录下所有文件名,...)

原文:https://www.cnblogs.com/sinicheveen/p/13680327.html

1. 环境

  • Linux(Ubuntu)
  • C++11
  • gcc 7.5.0
  • g++ 7.5.0
  • 这些常用操作封装为了一个 C++ 类 FileOperation
  • 对文件的操作基本都是使用的 C 函数,没有用 C++ 的 fstream 相关类
  • 针对 Linux 系统写的,涉及到 Linux 专有函数,因此对 Windows 系统可能不适用

2. 代码

FileOperation.h

复制代码
#pragma once

/*
*Environment:
*Linux(Ubuntu), C++11,gcc 7.5.0,g++ 7.5.0
*Description:
*文件和目录操作(e.g. 拷贝文件,拷贝目录,计算目录大小,...)
*/

#ifndef PARAMETER_FLOW
#define PARAMETER_FLOW
#define IN
#define OUT
#define INOUT
#endif    //PARAMETER_FLOW

#ifndef BASE_TYPE_DEF
#define BASE_TYPE_DEF
#include <stdint.h>
typedef int16_t          SHORT;
typedef uint16_t         USHORT;
typedef int32_t          INT;
typedef uint32_t         UINT;
typedef int64_t          DLONG;
typedef uint64_t         DULONG;
typedef void             VOID;
typedef bool             BOOL;
typedef signed char      CHAR;
typedef signed char      BYTE;
typedef unsigned char    UCHAR;
typedef float            FLOAT;
typedef double           DOUBLE;
#endif    //BASE_TYPE_DEF

#include <dirent.h>
#include <string>
#include <string.h>
#include <sys/stat.h>
#include <type_traits>
#include <unistd.h>
#include <utility>
#include <vector>
#include <sys/vfs.h>

using std::make_pair;
using std::pair;
using std::string;
using std::vector;

/*
Explain:
 - fileLongName:加了路径的文件名,e.g. /root/xxx/1.txt
 - fileShortName:没有加路径的文件名,e.g. 1.txt
 - dirLongName:加了路径的目录名,e.g. /root/xxx/MyDocuments
 - dirShortName:没有加路径的目录名,e.g. MyDocuments
*/

class FileOperation
{
public:
    /*
    *Function    : getDirSize
    *Description : 获取目录大小
    *Modify      : 2020.09.16
    *Input       : IN const string& dirLongName,目录名
    *            : OUT DLONG& dirSize,目录大小,单位:字节
    *Return      : pair<BOOL, string>,<函数是否执行成功,执行失败时的错误信息>
    *Caution     : 目录末尾不能有斜杠,e.g. 正确传参:/root/xxx,错误传参:/root/xxx/
    */
    static pair<BOOL, string> getDirSize(IN const string& dirLongName, OUT DLONG& dirSize);

    /*
    *Function    : getDirSizeAndMaxFileSize
    *Description : 获取目录大小和其中最大文件大小
    *Modify      : 2020.09.16
    *Input       : IN const string& dirLongName,目录名
    *            : OUT DLONG& dirSize,目录大小,单位:字节
    *            : OUT DLONG& maxFileSize,目录中最大文件大小,单位:字节
    *Return      : pair<BOOL, string>,<函数是否执行成功,执行失败时的错误信息>
    *Caution     : 目录末尾不能有斜杠,e.g. 正确传参:/root/xxx,错误传参:/root/xxx/
    */
    static pair<BOOL, string> getDirSizeAndMaxFileSize(IN const string& dirLongName, OUT DLONG& dirSize, OUT DLONG& maxFileSize);

    /*
    *Function    : getFileSize
    *Description : 获取文件大小
    *Modify      : 2020.09.16
    *Input       : IN const string& fileLongName,文件名
    *            : OUT DLONG& fileSize,文件大小
    *Return      : pair<BOOL, string>,<函数是否执行成功,执行失败时的错误信息>
    *Caution     :
    */
    static pair<BOOL, string> getFileSize(IN const string& fileLongName, OUT DLONG& fileSize);

    /*
    *Function    : getDiskSpace
    *Description : 获取磁盘总容量和剩余容量
    *Modify      : 2020.09.16
    *Input       : IN const string& diskPath,磁盘路径,e.g. /root
    *            : OUT DLONG& totalSpace,磁盘总容量,单位:字节
    *            : OUT DLONG& freeSpace,磁盘剩余容量,单位:字节
    *Return      : pair<BOOL, string>,<函数是否执行成功,执行失败时的错误信息>
    *Caution     :
    */
    static pair<BOOL, string> getDiskSpace(IN const string& diskPath, OUT DLONG& totalSpace, OUT DLONG& freeSpace);

    /*
    *Function    : getAllFileShortNamesInDir
    *Description : 获取目录下所有文件的短文件名
    *Modify      : 2020.09.16
    *Input       : IN const string& dirLongName,目录名
    *            : OUT vector<string>& allFileShortNames,目录下所有文件的短文件名
    *Return      : pair<BOOL, string>,<函数是否执行成功,执行失败时的错误信息>
    *Caution     : 目录末尾不能有斜杠,e.g. 正确传参:/root/xxx,错误传参:/root/xxx/
    *            :
    */
    static pair<BOOL, string> getAllFileShortNamesInDir(IN const string& dirLongName, OUT vector<string>& allFileShortNames);

    /*
    *Function    : getAllFileLongNamesInDir
    *Description : 获取目录下所有文件的长文件名
    *Modify      : 2020.09.16
    *Input       : IN const string& dirLongName,目录名
    *            : OUT vector<string>& allFileLongNames,目录下所有文件的长文件名
    *Return      : pair<BOOL, string>,<函数是否执行成功,执行失败时的错误信息>
    *Caution     : 目录末尾不能有斜杠,e.g. 正确传参:/root/xxx,错误传参:/root/xxx/
    *            :
    */
    static pair<BOOL, string> getAllFileLongNamesInDir(IN const string& dirLongName, OUT vector<string>& allFileLongNames);

    /*
    *Function    : moveFileOrDir
    *Description : 移动文件或文件夹
    *Modify      : 2020.09.16
    *Input       : IN const string& srcLongName,源文件(文件夹)名
    *            : IN const string& destLongName,目标文件(文件夹)名
    *Return      : pair<BOOL, string>,<函数是否执行成功,执行失败时的错误信息>
    *Caution     : 如果 srcLongName 和 destLongName 指定相同的路径,则进行重命名操作
    *            : 如果 srcLongName 和 destLongName 指定不同的路径,则文件(文件夹)将移动到新位置
    *            : 如果 destLongName 为现有文件,则覆盖现有文件
    *            : 如果 destLongName 为现有文件夹,则执行失败
    */
    static pair<BOOL, string> moveFileOrDir(IN const string& srcLongName, IN const string& destLongName);

    /*
    *Function    : removeFile
    *Description : 删除文件
    *Modify      : 2020.09.15
    *Input       : IN const string& fileLongName,文件名
    *Return      : pair<BOOL, string>,<函数是否执行成功,执行失败时的错误信息>
    *Caution     :
    */
    static pair<BOOL, string> removeFile(IN const string& fileLongName);

    /*
    *Function    : removeDir
    *Description : 删除目录
    *Modify      : 2020.09.16
    *Input       : IN const string& dirLongName,目录名
    *Return      : pair<BOOL, string>,<函数是否执行成功,执行失败时的错误信息>
    *Caution     : 目录末尾不能有斜杠,e.g. 正确传参:/root/xxx,错误传参:/root/xxx/
    */
    static pair<BOOL, string> removeDir(IN const string& dirLongName);

    /*
    *Function    : copyFile
    *Description : 复制文件
    *Modify      : 2020.09.16
    *Input       : IN const string& srcFileLongName,源文件名
    *            : IN const string& destLongFileName,目标文件名
    *Return      : pair<BOOL, string>,<函数是否执行成功,执行失败时的错误信息>
    *Caution     :
    */
    static pair<BOOL, string> copyFile(IN const string& srcFileLongName, IN const string& destLongFileName);

    /*
    *Function    : copyDir
    *Description : 复制目录
    *Modify      : 2020.09.15
    *Input       : IN const string& dirLongName,源目录名
    *            : IN string& destDirPath,目标目录名
    *Return      : pair<BOOL, string>,<函数是否执行成功,执行失败时的错误信息>
    *Caution     : 目录末尾不能有斜杠,e.g. 正确传参:/root/xxx,错误传参:/root/xxx/
    *            :
    */
    static pair<BOOL, string> copyDir(IN const string& srcDirPath, IN const string& destDirPath);

    /*
    *Function    : truncateFile
    *Description : 截断文件
    *Modify      : 2020.09.15
    *Input       : IN const string& fileLongName,文件名
    *            : IN const DLONG len,文件长度截断为长度 len
    *Return      : pair<BOOL, string>,<函数是否执行成功,执行失败时的错误信息>
    *Caution     : 如果文件先前大于此大小,则多余的数据会丢失
    *            : 如果文件先前较短,则将其扩展,扩展部分填充为空字节('\0')
    *            : 截断后 struct stat 的 st_size 变为 len
    */
    static pair<BOOL, string> truncateFile(IN const string& fileLongName, IN const DLONG len);

};    //FileOperation()
复制代码

 

FileOperation.cpp

复制代码
#include "FileOperation.h"

pair<BOOL, string> FileOperation::getDirSize(IN const string& dirLongName, OUT DLONG& dirSize)
{
    DIR* pDir = opendir(dirLongName.c_str());
    if (NULL != pDir)
    {
        struct dirent* pDirent = NULL;
        struct stat fileStat;
        string fileLongNameTmp;
        while (NULL != (pDirent = readdir(pDir)))
        {
            if (0 == strcmp(pDirent->d_name, ".") || 0 == strcmp(pDirent->d_name, ".."))
            {
                continue;
            }
            else if (DT_DIR != pDirent->d_type)
            {
                fileLongNameTmp = dirLongName + "/" + pDirent->d_name;
                if (0 == stat(fileLongNameTmp.c_str(), &fileStat))
                {
                    dirSize += fileStat.st_size;
                }
                else
                {
                    return make_pair(false, "file long name: " + fileLongNameTmp + ", error message: " + strerror(errno));
                }
            }
            else
            {
                pair<BOOL, string> exeStat = getDirSize(dirLongName + "/" + pDirent->d_name, dirSize);
                if (false == exeStat.first)
                {
                    return exeStat;
                }
            }
        }

        return make_pair(true, "");
    }
    else
    {
        return make_pair(false, "dir long name: " + dirLongName + ", error message: " + strerror(errno));
    }
}    //getDirSize()

pair<BOOL, string> FileOperation::getDirSizeAndMaxFileSize(IN const string& dirLongName, OUT DLONG& dirSize, OUT DLONG& maxFileSize)
{
    DIR* pDir = opendir(dirLongName.c_str());
    if (NULL != pDir)
    {
        struct dirent* pDirent = NULL;
        struct stat fileStat;
        string fileLongNameTmp;
        while (NULL != (pDirent = readdir(pDir)))
        {
            if (0 == strcmp(pDirent->d_name, ".") || 0 == strcmp(pDirent->d_name, ".."))
            {
                continue;
            }
            else if (DT_DIR != pDirent->d_type)
            {
                fileLongNameTmp = dirLongName + "/" + pDirent->d_name;
                if (0 == stat(fileLongNameTmp.c_str(), &fileStat))
                {
                    dirSize += fileStat.st_size;
                    if (fileStat.st_size > maxFileSize)
                    {
                        maxFileSize = fileStat.st_size;
                    }
                }
                else
                {
                    return make_pair(false, "file long name: " + fileLongNameTmp + ", error message: " + strerror(errno));
                }
            }
            else
            {
                pair<BOOL, string> exeStat = getDirSizeAndMaxFileSize(dirLongName + "/" + pDirent->d_name, dirSize, maxFileSize);
                if (false == exeStat.first)
                {
                    return exeStat;
                }
            }
        }

        return make_pair(true, "");
    }
    else
    {
        return make_pair(false, "dir long name: " + dirLongName + ", error message: " + strerror(errno));
    }
}    //getDirSizeAndMaxFileSize()

pair<BOOL, string> FileOperation::getFileSize(IN const string& fileLongName, OUT DLONG& fileSize)
{
    fileSize = 0;

    struct stat fileStat;
    if (0 == stat(fileLongName.c_str(), &fileStat))
    {
        fileSize = fileStat.st_size;
        return make_pair(true, "");
    }
    else
    {
        return make_pair(false, "file long name: " + fileLongName + ", error message: " + strerror(errno));
    }
}    //getFileSize()

pair<BOOL, string> FileOperation::getDiskSpace(IN const string& diskPath, OUT DLONG& totalSpace, OUT DLONG& freeSpace)
{
    totalSpace = 0;
    freeSpace = 0;

    struct statfs diskStatfs;
    if (statfs(diskPath.c_str(), &diskStatfs) >= 0)
    {
        totalSpace = (DLONG)diskStatfs.f_bsize * (DLONG)diskStatfs.f_blocks;
        freeSpace = (DLONG)diskStatfs.f_bsize * (DLONG)diskStatfs.f_bfree;
        return make_pair(true, "");
    }
    else
    {
        return make_pair(false, "disk path: " + diskPath + ", error message: " + strerror(errno));
    }
}    //getDiskSpace()

pair<BOOL, string> FileOperation::getAllFileShortNamesInDir(IN const string& dirLongName, OUT vector<string>& allFileShortNames)
{
    DIR* pDir = opendir(dirLongName.c_str());
    if (NULL != pDir)
    {
        struct dirent* pDirent = NULL;
        struct stat fileStat;
        while (NULL != (pDirent = readdir(pDir)))
        {
            if (0 == strcmp(pDirent->d_name, ".") || 0 == strcmp(pDirent->d_name, ".."))
            {
                continue;
            }
            else if (DT_DIR != pDirent->d_type)
            {
                allFileShortNames.emplace_back(pDirent->d_name);
            }
            else
            {
                pair<BOOL, string> exeStat = getAllFileShortNamesInDir(dirLongName + "/" + pDirent->d_name, allFileShortNames);
                if (false == exeStat.first)
                {
                    return exeStat;
                }
            }
        }

        return make_pair(true, "");
    }
    else
    {
        return make_pair(false, "dir long name: " + dirLongName + ", error message: " + strerror(errno));
    }
}    //getAllFileShortNamesInDir()

pair<BOOL, string> FileOperation::getAllFileLongNamesInDir(IN const string& dirLongName, OUT vector<string>& allFileLongNames)
{
    DIR* pDir = opendir(dirLongName.c_str());
    if (NULL != pDir)
    {
        struct dirent* pDirent = NULL;
        struct stat fileStat;
        while (NULL != (pDirent = readdir(pDir)))
        {
            if (0 == strcmp(pDirent->d_name, ".") || 0 == strcmp(pDirent->d_name, ".."))
            {
                continue;
            }
            else if (DT_DIR != pDirent->d_type)
            {
                allFileLongNames.emplace_back(dirLongName + "/" + pDirent->d_name);
            }
            else
            {
                pair<BOOL, string> exeStat = getAllFileLongNamesInDir(dirLongName + "/" + pDirent->d_name, allFileLongNames);
                if (false == exeStat.first)
                {
                    return exeStat;
                }
            }
        }

        return make_pair(true, "");
    }
    else
    {
        return make_pair(false, "dir long name: " + dirLongName + ", error message: " + strerror(errno));
    }
}    //getAllFileLongNamesInDir()

pair<BOOL, string> FileOperation::moveFileOrDir(IN const string& srcLongName, IN const string& destLongName)
{
    if (0 == rename(srcLongName.c_str(), destLongName.c_str()))
    {
        return make_pair(true, "");
    }
    else
    {
        return make_pair(false, "src file long name: " + srcLongName +
            ", dest file long name: " + destLongName + ", error message: " + strerror(errno));
    }
}    //moveFileOrDir()

pair<BOOL, string> FileOperation::removeFile(IN const string& fileLongName)
{
    if (0 == remove(fileLongName.c_str()))
    {
        return make_pair(true, "");
    }
    else
    {
        return make_pair(false, "file long name: " + fileLongName + ", error message: " + strerror(errno));
    }
}    //removeFile()

pair<BOOL, string> FileOperation::removeDir(IN const string& dirLongName)
{
    DIR* pDir = opendir(dirLongName.c_str());
    if (NULL != pDir)
    {
        struct dirent* pDirent = NULL;
        struct stat fileStat;
        while (NULL != (pDirent = readdir(pDir)))
        {
            if (0 == strcmp(pDirent->d_name, ".") || 0 == strcmp(pDirent->d_name, ".."))
            {
                continue;
            }
            else if (DT_DIR != pDirent->d_type)
            {
                pair<BOOL, string> exeStat = removeFile(dirLongName + "/" + pDirent->d_name);
                if (false == exeStat.first)
                {
                    return exeStat;
                }
            }
            else
            {
                pair<BOOL, string> exeStat = removeDir(dirLongName + "/" + pDirent->d_name);
                if (false == exeStat.first)
                {
                    return exeStat;
                }
            }
        }

        return make_pair(true, "");
    }
    else
    {
        return make_pair(false, "dir long name: " + dirLongName + ", error message: " + strerror(errno));
    }
}    //removeDir()

pair<BOOL, string> FileOperation::copyFile(IN const string& srcFileLongName, IN const string& destLongFileName)
{
    INT len = 0;
    FILE* pSrcFile = NULL;
    FILE* pDestFile = NULL;
    UINT bufferSize = 1 * 1024 * 1024;    //设置的过大也不会对性能有什么显著提升
    vector<CHAR> buffer(bufferSize, 0);

    if (NULL == (pSrcFile = fopen(srcFileLongName.c_str(), "rb")))
    {
        return make_pair(false, "source file long name: " + srcFileLongName + ", error message: " + strerror(errno));

    }
    if (NULL == (pDestFile = fopen(destLongFileName.c_str(), "wb")))
    {
        return make_pair(false, "dest file long name: " + destLongFileName + ", error message: " + strerror(errno));
    }

    while ((len = fread(&buffer[0], sizeof(BYTE), bufferSize, pSrcFile)) > 0)
    {
        fwrite(&buffer[0], sizeof(CHAR), len, pDestFile);
    }
    fclose(pDestFile);
    fclose(pSrcFile);

    return make_pair(true, "");
}    //copyFile()

pair<BOOL, string> FileOperation::copyDir(IN const string& srcDirPath, IN const string& destDirPath)
{
    if (0 != mkdir(destDirPath.c_str(), 00777))
    {
        return make_pair(false, "dest dir path: " + destDirPath + ", error message: " + strerror(errno));
    }

    DIR* pDir = opendir(srcDirPath.c_str());
    if (NULL != pDir)
    {
        struct dirent* pDirent = NULL;
        while (NULL != (pDirent = readdir(pDir)))
        {
            if (0 == strcmp(pDirent->d_name, ".") || 0 == strcmp(pDirent->d_name, ".."))
            {
                continue;
            }
            else if (DT_DIR != pDirent->d_type)
            {
                pair<BOOL, string> exeStat = copyFile(srcDirPath + "/" + pDirent->d_name, destDirPath + "/" + pDirent->d_name);
                if (false == exeStat.first)
                {
                    return exeStat;
                }
            }
            else
            {
                pair<BOOL, string> exeStat = copyDir(srcDirPath + "/" + pDirent->d_name, destDirPath + "/" + pDirent->d_name);
                if (false == exeStat.first)
                {
                    return exeStat;
                }
            }
        }

        return make_pair(true, "");
    }
    else
    {
        return make_pair(false, "source dir path: " + srcDirPath + ", error message: " + strerror(errno));
    }
}    //copyDir()

pair<BOOL, string> FileOperation::truncateFile(IN const string& fileLongName, IN const DLONG len)
{
    if (0 == truncate(fileLongName.c_str(), len))
    {
        return make_pair(true, "");
    }
    else
    {
        return make_pair(false, "file long name: " + fileLongName + ", error message: " + strerror(errno));
    }
}    //truncateFile()
复制代码

posted on 2020-09-16 17:39  陈小羊  阅读(1495)  评论(0编辑  收藏  举报