利用 boost 库,编写c++类 FilesDirectoryTree,获得某个文件夹下符合某种格式要求(pcd)的文件路径,并按照降序或升序排列

来源:互联网 发布:淘宝网超市货架 编辑:程序博客网 时间:2024/05/20 23:35
#pragma once
#include <iostream>
#include <boost/filesystem.hpp>
#include <boost/xpressive/xpressive_dynamic.hpp>
#include <boost/algorithm/string.hpp>
#include <string>
#include <vector>


enum FilesSortMark
{
ASCEND,
DESCEND,
NONE
};


class FilesDirectoryTree
{


private:
typedef std::pair<std::string, int> PAIR;


//Define outside
static bool cmpAscend(const PAIR& x, const PAIR& y)
{
return x.second < y.second;
}
static bool cmpDescend(const PAIR& x, const PAIR& y)
{
return x.second > y.second;
}


public:
FilesDirectoryTree(const boost::filesystem::path &src,const std::string &form=std::string("NO_FORMATE"),const FilesSortMark mark=NONE);
~FilesDirectoryTree();
boost::shared_ptr<std::vector<std::vector<std::string>>> getDirectoryTree();


private:
void getDirectoryTreeRecur(const boost::filesystem::path &src);
bool constructSregex(const std::string form);
void sortDirectoryAccordingMark(const std::vector<std::string> &input,std::vector<std::string> &output);
int getSNformDirectory(const std::string &input);
void strReverseLR(std::string &str);
FilesSortMark m_mark;


const boost::filesystem::path m_src;
boost::shared_ptr<std::vector<std::vector<std::string>>> m_directoryTree;
bool m_bFormat;
boost::xpressive::sregex m_reg;

};


FilesDirectoryTree::FilesDirectoryTree(const boost::filesystem::path &src, const std::string &form, const FilesSortMark mark) :m_src(src), m_mark(mark)
{
//为保存文件路径分配内存
m_directoryTree = boost::shared_ptr<std::vector<std::vector<std::string>>>(new std::vector<std::vector<std::string>>);


//根据文件格式构造过滤文件的正则表达式
m_bFormat = constructSregex(form);//if false,no format requires
}




FilesDirectoryTree::~FilesDirectoryTree()
{
}


boost::shared_ptr<std::vector<std::vector<std::string>>> FilesDirectoryTree::getDirectoryTree()
{
getDirectoryTreeRecur(m_src);
return m_directoryTree;
}


//递归获得总文件夹下的所有文件
void FilesDirectoryTree::getDirectoryTreeRecur(const boost::filesystem::path &src)
{
std::vector<std::string> rawFiles;
rawFiles.reserve(15);
for (boost::filesystem::directory_iterator it(src); it != boost::filesystem::directory_iterator(); ++it)
{
const boost::filesystem::path newSrc = src / it->path().filename();


if (boost::filesystem::is_directory(newSrc))
{
getDirectoryTreeRecur(newSrc);
}
else if (boost::filesystem::is_regular_file(newSrc))
{
if (!m_bFormat)
{
rawFiles.push_back(newSrc.string());
}
else if (boost::xpressive::regex_match(newSrc.filename().string(), m_reg))
{
rawFiles.push_back(newSrc.string());
}

}
}
if (rawFiles.size() > 0)
{
if (m_mark==NONE)
{
m_directoryTree->push_back(rawFiles);
return;
}
else
{
//对路径按照数字大小排序
std::vector<std::string> sortedFiles;
sortDirectoryAccordingMark(rawFiles, sortedFiles);
m_directoryTree->push_back(sortedFiles);
return;
}
}
}


/*如果传递是std::string类型字符串,但不是const的!!


  返回类型为std::string,那你将不必再定义一个新的字符串变量


    节省空间,注意:string类型可以直接接受字符串字面值就是啦..


*/
void FilesDirectoryTree::strReverseLR(std::string &str)
{
for (int i = 0; i < str.length() / 2; ++i)
{
char c = str[i];
str[i] = str[str.length() - i - 1];
str[str.length() - i - 1] = c;
}
}


int FilesDirectoryTree::getSNformDirectory(const std::string &input)
{
std::string str_SN;
auto posEnd = input.length();
auto pos = input.find_last_of('.');
char cTmp = input.at(pos - 1);
if (cTmp >= '0'&&cTmp <= '9')
{
pos--;
do
{
str_SN.push_back(cTmp);
pos--;
if (pos >= 0)
cTmp = input.at(pos);
else
break;
} while (cTmp >= '0'&&cTmp <= '9');
strReverseLR(str_SN);
std::stringstream ss(str_SN);
int toReturn = 0;
ss >> toReturn;
return toReturn;
}
else
{
cTmp = input.at(pos + 1);
if (cTmp >= '0'&&cTmp <= '9')
{
do
{
str_SN.push_back(cTmp);
pos++;
if (pos <= posEnd)
cTmp = input.at(pos);
else
break;
} while (cTmp >= '0'&&cTmp <= '9');
std::stringstream ss(str_SN);
int toReturn = 0;
ss >> toReturn;
return toReturn;
}
else
return -1;
}
}


void FilesDirectoryTree::sortDirectoryAccordingMark(const std::vector<std::string> &input, std::vector<std::string> &output)
{
//构造待排列路径的pair类型
std::vector<PAIR> pairVec;
for (std::vector<std::string>::const_iterator it = input.begin(); it < input.end(); it++)
{
PAIR pairTmp(*it, getSNformDirectory(*it));
pairVec.push_back(pairTmp);
}
if (m_mark==ASCEND)
{
sort(pairVec.begin(), pairVec.end(), FilesDirectoryTree::cmpAscend);
}


if (m_mark == DESCEND)
{
sort(pairVec.begin(), pairVec.end(), FilesDirectoryTree::cmpDescend);
}


for (std::vector<PAIR>::const_iterator it = pairVec.begin(); it < pairVec.end(); it++)
{
output.push_back(it->first);
}
}


//根据文件后缀格式,构造符合正则表达的后缀格式
bool FilesDirectoryTree::constructSregex(const std::string form)
{
if (form.find("NO_FORMATE") != std::string::npos)
{
return false;
}
else
{
std::string formTmp(form);
//找到任意符 * 的位置,将其更改为 .* 
auto pos = formTmp.find_first_of('*', 0);
if (pos != std::string::npos)
{
//例如 *.pcd* *.pcd
do
{
formTmp.insert(pos, ".");
auto posTmp = pos + 1;
pos = formTmp.find_first_of('*', posTmp);
} while (pos != std::string::npos);


m_reg = boost::xpressive::sregex::compile(formTmp);
return true;
}
else
{
//例如 .pcd
//添加字符串 .*
formTmp.insert(0, ".*");
formTmp.push_back('.');
formTmp.push_back('*');
m_reg = boost::xpressive::sregex::compile(formTmp);
return true;
}
}
}


int main()
{
boost::shared_ptr<std::vector<std::vector<std::string>>> directoryTree;
FilesDirectoryTree filesDirectoryTree("D:\\总文件夹","pcd", ASCEND);
directoryTree = filesDirectoryTree.getDirectoryTree();
return 0;
}

阅读全文
0 0