【转载】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()