1. 程式人生 > >C++獲取檔名稱,去除字尾,排序,移動相關(VS版本和命令列即指令碼版本)

C++獲取檔名稱,去除字尾,排序,移動相關(VS版本和命令列即指令碼版本)

功能:
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;
}