最近项目中需要用到遍历出指定文件夹下所有文件列表,又没有现成得接口,只能通过调用系统接口实现,于是查阅和整理了一下,写了一个支持跨平台(windows和linux系统)的接口:
/**************************************************************
* 功能:遍历文件夹下所有文件列表,目前只支持一级目录
* 输入参数:
* strFileFolder:文件夹
* 输出参数:
* vtFilePaths:文件列表
* ************************************************************/
void getFilePaths(const std::string& strFileFolder, std::vector<std::string>& vtFilePaths);
具体实现如下:
#include <iostream>
#include <string>
#include <stdlib.h>
#include <string.h>
#ifdef __linux__
#include <dirent.h>
#else
#include <io.h>
#endif // __linux__
#include <vector>
/**************************************************************
* 功能:遍历文件夹下所有文件列表,目前只支持一级目录
* 输入参数:
* strFileFolder:文件夹
* 输出参数:
* vtFilePaths:文件列表
* ************************************************************/
void getFilePaths(const std::string& strFileFolder, std::vector<std::string>& vtFilePaths)
{
#ifdef __linux__
DIR* pDir = nullptr;
if (!(pDir = opendir(strFileFolder.data())))
{
std::cout << "file folder doesn't exist!" << std::endl;
return;
}
struct dirent* ptr = nullptr;
while (0 != (ptr = readdir(pDir)))
{
if (0 != strcmp(ptr->d_name, ".") && 0 != strcmp(ptr->d_name, ".."))
{
vtFilePaths.emplace_back(strFileFolder + "/" + ptr->d_name);
}
}
closedir(pDir);
#else
struct _finddata_t fileInfo;
//std::string strFileInfo = strFileFolder + "/*.jpg"; // ok
std::string strFileInfo = strFileFolder + "/*.*"; // ok
//std::string strFileInfo = strFileFolder + "\\*"; // ok
long long hFd = _findfirst(strFileInfo.data(), &fileInfo);
if (-1 == hFd)
{
_findclose(hFd);
std::cout << "file folder _findfirst error!" << std::endl;
return;
}
std::string strFilePath = "";
do
{
strFilePath = strFileFolder + "/" + fileInfo.name;
if (_A_ARCH == fileInfo.attrib)
{
vtFilePaths.emplace_back(strFilePath);
}
} while (0 == _findnext(hFd, &fileInfo));
_findclose(hFd);
#endif
return;
}
测试用例如下:
void getFilePathsTest()
{
std::string strFileFolder = "./data/images";
std::vector<std::string> vtFilePaths;
getFilePaths(strFileFolder, vtFilePaths);
size_t size = vtFilePaths.size();
printf("%s file count: %d.\r\n", strFileFolder.data(), size);
for (size_t i = 0; i < 8 && i < size; ++i)
{
printf("file: %s.\r\n", vtFilePaths.at(i).data());
}
strFileFolder = "./data/radars";
vtFilePaths.clear();
getFilePaths(strFileFolder, vtFilePaths);
size = vtFilePaths.size();
printf("%s file count: %d.\r\n", strFileFolder.data(), size);
for (size_t i = 0; i < 8 && i < size; ++i)
{
printf("file: %s.\r\n", vtFilePaths.at(i).data());
}
strFileFolder = "./data/cans";
vtFilePaths.clear();
getFilePaths(strFileFolder, vtFilePaths);
size = vtFilePaths.size();
printf("%s file count: %d.\r\n", strFileFolder.data(), size);
for (size_t i = 0; i < 8 && i < size; ++i)
{
printf("file: %s.\r\n", vtFilePaths.at(i).data());
}
return;
}
扩展业务:
#include <math.h>
#include <cmath>
// 文件概要信息
struct FileAbsInfo
{
std::string strPath;
uint64_t ui64Timestamp;
FileAbsInfo()
{
strPath = "";
ui64Timestamp = 0;
}
};
// 文件查找参数
struct FindParam
{
bool bQueryAll;
size_t iSrcFolderSize;
size_t iIndexPos;
size_t iOffset;
int iTimeSpan; // 单位ms
uint64_t ui64Timestamp; // 单位ms
double dRatio;
FindParam()
{
memset(this, 0, sizeof (FindParam));
}
};
bool compareFileInfo(const FileAbsInfo& info1, const FileAbsInfo& info2)
{
//return (info1.ui64Timestamp > info2.ui64Timestamp); // 降序
return (info1.ui64Timestamp < info2.ui64Timestamp); // 升序
}
uint64_t getFileTimestamp(const std::string& strFileName)
{
uint64_t ui64Timestamp = 0;
size_t pos = strFileName.find_first_of('.');
if (std::string::npos != pos)
{
std::string strTimestamp = strFileName.substr(0, pos);
ui64Timestamp = std::stoull(strTimestamp);
}
return ui64Timestamp;
}
void getFilePaths(const std::string& strFileFolder, std::vector<FileAbsInfo>& vtFileInfos)
{
#ifdef __linux__
DIR* pDir = opendir(strFileFolder.data());
if (!pDir)
{
std::cout << "file folder doesn't exist!" << std::endl;
return;
}
FileAbsInfo stFileInfo;
struct dirent* ptr = nullptr;
while (0 != (ptr = readdir(pDir)))
{
if (0 != strcmp(ptr->d_name, ".") && 0 != strcmp(ptr->d_name, ".."))
{
stFileInfo.strPath = strFileFolder + "/" + ptr->d_name;
stFileInfo.ui64Timestamp = getFileTimestamp(ptr->d_name);
vtFileInfos.emplace_back(stFileInfo);
}
}
closedir(pDir);
#else
struct _finddata_t fileInfo;
//std::string strFileInfo = strFileFolder + "/*.jpg"; // ok
std::string strFileInfo = strFileFolder + "/*.*"; // ok
//std::string strFileInfo = strFileFolder + "\\*"; // ok
long long hFd = _findfirst(strFileInfo.data(), &fileInfo);
if (-1 == hFd)
{
_findclose(hFd);
std::cout << "file folder _findfirst error!" << std::endl;
return;
}
FileAbsInfo stFileInfo;
do
{
if (_A_ARCH == fileInfo.attrib)
{
stFileInfo.strPath = strFileFolder + "/" + fileInfo.name;
stFileInfo.ui64Timestamp = getFileTimestamp(fileInfo.name);
vtFileInfos.emplace_back(stFileInfo);
}
} while (0 == _findnext(hFd, &fileInfo));
_findclose(hFd);
#endif
sort(vtFileInfos.begin(), vtFileInfos.end(), compareFileInfo);
return;
}
std::string getRelateFilePath(const FindParam& stFindParam, std::vector<FileAbsInfo>& vtFileInfo)
{
std::string strPath = "";
size_t iFolderSize = vtFileInfo.size();
int iStPos = 0, iEdPos = static_cast<int>(iFolderSize);
if (!(stFindParam.bQueryAll))
{
iStPos = static_cast<int>(stFindParam.dRatio * stFindParam.iIndexPos - stFindParam.iOffset); // 毫米波雷达数据是图像数据的${dRatio}倍左右
iEdPos = static_cast<int>(stFindParam.dRatio * stFindParam.iIndexPos + stFindParam.iOffset); // 毫米波雷达数据是图像数据的${dRatio}倍左右
}
iStPos = iStPos < 0 ? 0 : iStPos;
iEdPos = iEdPos > static_cast<int>(iFolderSize) ? static_cast<int>(iFolderSize) : iEdPos;
//LOG_DEBUG("timestamp: %llu, index: %u, start: %u, end: %u, size %u.", stFindParam.ui64Timestamp, stFindParam.iIndexPos, iStPos, iEdPos, vtFileInfo.size());
// 升序排序,找到第一个在${ui32TimeSpan}时间差范围内的即可
for (size_t i = static_cast<size_t>(iStPos); i < static_cast<size_t>(iEdPos); ++i)
{
if (stFindParam.iTimeSpan > abs(static_cast<int>(stFindParam.ui64Timestamp - vtFileInfo[i].ui64Timestamp)))
{
strPath = vtFileInfo[i].strPath;
break;
}
}
return strPath;
}
static std::string findRadarDataFilePath(size_t iIndexPos, uint64_t ui64Timestamp, size_t iSrcFolderSize, std::vector<FileAbsInfo> &vtFileInfo)
{
size_t iDstFolderSize = vtFileInfo.size();
FindParam stFindParam;
stFindParam.bQueryAll = false;
stFindParam.iSrcFolderSize = iSrcFolderSize;
stFindParam.iIndexPos = iIndexPos;
stFindParam.ui64Timestamp = ui64Timestamp;
stFindParam.iOffset = 300;
stFindParam.dRatio = (static_cast<double>(iDstFolderSize) * 1.0) / static_cast<double>(stFindParam.iSrcFolderSize);
stFindParam.iTimeSpan = 45;
std::string strPath = getRelateFilePath(stFindParam, vtFileInfo);
if (strPath.empty())
{
// 如果第一次没有找到,进行全局查找
stFindParam.bQueryAll = true;
strPath = getRelateFilePath(stFindParam, vtFileInfo);
// 如果第二次没有找到,再放大一次时间差范围进行查找,保障大部分能够找到
if (strPath.empty())
{
stFindParam.iTimeSpan = 250;
strPath = getRelateFilePath(stFindParam, vtFileInfo);
}
}
return strPath;
}
void getFilePathsTest()
{
std::string strFileFolder = "./data/images";
std::vector<FileAbsInfo> vtFilePaths;
getFilePaths(strFileFolder, vtFilePaths);
std::string strFileRadarFolder = "./data/radars";
std::vector<FileAbsInfo> vtFileRadarPaths;
getFilePaths(strFileRadarFolder, vtFileRadarPaths);
std::string strFileCanFolder = "./data/radars_can";
std::vector<FileAbsInfo> vtFileCanPaths;
getFilePaths(strFileCanFolder, vtFileCanPaths);
size_t size = vtFilePaths.size();
printf("file count : % d, % d, % d.\r\n", size, vtFileRadarPaths.size(), vtFileCanPaths.size());
for (size_t i = 0; i < size; ++i)
{
std::string strRadar = findRadarDataFilePath(i, vtFilePaths.at(i).ui64Timestamp, size, vtFileRadarPaths);
std::string strCan = findRadarDataFilePath(i, vtFilePaths.at(i).ui64Timestamp, size, vtFileCanPaths);
if (!(strRadar.empty()) && !(strCan.empty()))
{
#if 0
printf("**************FOUND*************\r\n");
printf("index: %d, file: %s, %llu.\r\n", i, vtFilePaths.at(i).strPath.data(), vtFilePaths.at(i).ui64Timestamp);
printf("relate radar file: %s.\r\n", strRadar.data());
printf("relate can file: %s.\r\n", strCan.data());
printf("***************************\r\n");
#endif
}
else
{
printf("**************NOT FOUND*************\r\n");
printf("index: %d, file: %s, %llu.\r\n", i, vtFilePaths.at(i).strPath.data(), vtFilePaths.at(i).ui64Timestamp);
printf("relate radar file: %s.\r\n", strRadar.data());
printf("relate can file: %s.\r\n", strCan.data());
printf("***************************\r\n");
}
}
return;
}