功能:
1. 获取某一文件夹下的所有文件名
2.去除文件名后缀
3.将去除后缀的文件名转为整形,并排序
4.将排序好的文件分组,分别存入不同的文件夹
note:
1.用到了快速排序
2.利用文件流实现文件的移动,简单易懂,比MoveFile函数好用
3.利用流实现string转int(c++推荐)
VSb版本主程序:可直接在VS2015下运行
#include <iostream>
#include <io.h>
#include <xstring>
#include <vector>
#include <sstream>
#include <fstream>
#include <windows.h>
#include <direct.h>
using namespace std;
void getFiles(string path, vector<string>& files);
string removeSuffix(string fileName);
int str2int(const string str);
void quickSort(vector<int>& vec, int startIndex, int endIndex);
int partition(vector<int>& vec, int startIndex, int endIndex);
void mkdir(const vector<int> numFiles, const string dirPath);
int main()
{
vector<string> files;
const char* directory = "D:\\workspace\\20181112\\pic\\20171114_1456_A";
string dirPath = "D:\\workspace\\20181112\\pic\\20171114_1456_A";
getFiles(directory, files);
//去除后缀,并转为int
vector<string> remFiles;
vector<int> numFiles;
int nSize = files.size();
for (int i = 0; i < nSize; i++)
{
string remFile = removeSuffix(files[i]);
int num = str2int(remFile);
remFiles.push_back(remFile);
numFiles.push_back(num);
}
quickSort(numFiles, 0, numFiles.size() - 1);
mkdir(numFiles, dirPath);
cout << "Done!" << endl;
return 0;
}
void getFiles(string path, vector<string>& files)
{
//文件句柄:文件的唯一标识
//long hFile = 0;//32位能跑动
intptr_t hFile = 0;//因为_findfirst和_findnext返回intptr_t而非long型
//定义存储文件信息的结构体
struct _finddata_t fileinfo;
string p;
if ((hFile = _findfirst(p.assign(path).append("\\*").c_str(), &fileinfo)) != -1)//string转化为c_str即C类型的字符串
{
do
{
//如果是目录,迭代之
//如果不是,加入列表
if ((fileinfo.attrib & _A_SUBDIR))//&:attrib和_A_SUBDIR做一次与运算,返回1则为_A_SUBDIR(文件夹)
{
if (strcmp(fileinfo.name, ".") != 0 && strcmp(fileinfo.name, "..") != 0)
getFiles(p.assign(path).append("\\").append(fileinfo.name), files);//递归
}
else
{
files.push_back(p.assign(path).append("\\").append(fileinfo.name));
}
}
while (_findnext(hFile, &fileinfo) == 0);
_findclose(hFile);
}
}
string removeSuffix(string fileName)
{
const char* full_name = fileName.c_str();
const char* mn_first = full_name;
int tmp = strlen(full_name);//长度不包含'/0'
const char* mn_last = full_name /*+ strlen(full_name)*/;
if (strrchr(full_name, '\\') != NULL)//去除路径,只留文件名
mn_first = strrchr(full_name, '\\') + 1;
else if (strrchr(full_name, '/') != NULL)//去除linux下的文件路径
mn_first = strrchr(full_name, '/') + 1;
if (strrchr(full_name, '.') != NULL)
mn_last = strrchr(full_name, '.');//获取.*后缀
if (mn_last < mn_first)//地址比较
mn_last = full_name + strlen(full_name);
fileName.assign(mn_first, mn_last);//参数10001.jpg和.jpg
return fileName;
}
int str2int(const string str)
{
int tmp;
stringstream stream(str);
stream >> tmp;
return tmp;
}
void quickSort(vector<int>& vecVec, int startIndex, int endIndex)
{
if (startIndex < endIndex)
{
int pivot = partition(vecVec, startIndex, endIndex);
quickSort(vecVec, startIndex, pivot);
quickSort(vecVec, pivot + 1, endIndex);
}
}
int partition(vector<int>& vec, int startIndex, int endIndex)
{
int left = startIndex;
int right = endIndex;
int pivot = vec[startIndex];
while (left < right)
{
while (left < right && vec[right] >= pivot)
right--;
while (left < right && vec[left] <= pivot)
left++;
int tmp = vec[left];
vec[left] = vec[right];
vec[right] = tmp;
}
int tmp = vec[left];
vec[left] = pivot;
vec[startIndex] = tmp;
return left;
}
void mkdir(const vector<int> numFiles, const string dirPath)
{
vector<vector<int>> nameGroup;
int nSize = numFiles.size();
vector<int> tmp;
//分组
for (int i = 0;i < nSize - 1; i++)
{
int dif = numFiles[i + 1] - numFiles[i];
if (dif == 2)
{
tmp.push_back(numFiles[i]);
}
else
{
tmp.push_back(numFiles[i]);
nameGroup.push_back(tmp);
tmp.clear();
}
}
//处理边界
tmp.push_back(numFiles.back());
nameGroup.push_back(tmp);
//建立目录并移动文件
int nDir = nameGroup.size();
vector<string> strGroup;
for (int i = 0; i < nDir; i++)
{
int n_1 = nameGroup[i].front();
int n_2 = nameGroup[i].back();
string str_1 = to_string(n_1);
string str_2 = to_string(n_2);
string strDir = dirPath + "\\" + str_1 + "-" + str_2;
const char* dir = strDir.c_str();
_mkdir(dir);
//文件的移动
for (int j = 0; j < nameGroup[i].size(); j++)
{
string strFileName = dirPath + "\\" + to_string(nameGroup[i][j]) + ".jpg";//源文件
string strFileDir = strDir +"\\"+ to_string(nameGroup[i][j]) + ".jpg";//目标文件
const char* cN = strFileName.c_str();
const char* cD = dir;
ifstream ifs(strFileName, ios_base::binary);//读入流
if (!ifs.is_open())
{
break;
}
ofstream ofs(strFileDir, ios_base::binary);
ofs << ifs.rdbuf();
ifs.close();
if (remove(cN) != 0)
{
cout << "删除失败" << endl;
break;
}
}
cout << "第" << i << "组拷贝完成" << endl;
}
}
命令行版本:
将release版本的.exe程序拷贝到存放图片的文件目录下,在shell下运行
./mkdir.exe
命令行下在VS调试:
程序:只有main函数改变
int main(int argc,char* argv[])
{
if (argc != 1)
{
cout << "参数应为1" << endl;
cout << "False!" << endl;
return 3;
}
vector<string> files;
const char* directory = "./";
string dirPath = "./";
getFiles(directory, files);
//去除后缀,并转为int
vector<string> remFiles;
vector<int> numFiles;
int nSize = files.size();
for (int i = 0; i < nSize; i++)
{
string remFile = removeSuffix(files[i]);
int num = str2int(remFile);
remFiles.push_back(remFile);
numFiles.push_back(num);
}
quickSort(numFiles, 0, numFiles.size() - 1);
mkdir(numFiles, dirPath);
cout << "Done!" << endl;
return 0;
}