作者:翟天保Steven
版权声明:著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处
在日常工作中,必然会和各类文件打交道,如何高效地操作处理文件是提高工作效率的关键。Excel、VB、Python等等用好了,都可以将傻瓜操作(批量复制粘贴、筛选查找等)自动化,仅需秒级时间,即可完成他人小时级时间的工作量,剩下的时间至于是摸鱼还是自主学习,就看个人了。由此可见,高效的工作方法选对了是多么重要。
本文所要实现的需求:有一文件夹A,大概有千级往上数量的录音文件,每个录音文件名格式为“手机号码+乱码.xxx”;手头另有一号码表格B,存放了200个左右的11位手机号码。要求将文件夹A中号码与表格B号码匹配的录音,拷贝到另一文件夹C中。
如果用EXCEL,可以借助VLOOKUP,完成筛选,再用Bat的copy指令,完成拷贝操作。(方法多种多样,有其他思路的欢迎评论区留言,一同交流学习)
那如何用C++实现,本文将进行详细的讲解,提供源码和简易测试代码。(实现方法同样多种多样,本文仅用了一种方案,仅供参考)
要想完成该功能,可以拆分一下各个子功能。
1)我们将文件夹A的路径用字符串from存储下来,文件夹C的路径用字符串to存储下来,同时定义一个表格B的路径。
- string from = "C:\\Users\\Administrator\\Desktop\\current\\";
- string to = "C:\\Users\\Administrator\\Desktop\\target\\";
- string sheetpath= "C:\\Users\\Administrator\\Desktop\\current\\test.txt";
2)设计一个getFiles函数,用于获取目标文件夹下目标文件信息,并存放在vector中。
- // 获取目标文件夹下目标文件信息
- void getFiles(std::string path, vector
& files, vector& filesname, std::string suffix) - {
- intptr_t hFile = 0;
- struct _finddata_t fileinfo;
- string p;
- // 寻找当前文件夹下后缀为mp3的文件
- if ((hFile = _findfirst(p.assign(path).append(suffix).c_str(), &fileinfo)) != -1) {
- do {
- // files存放文件全路径
- files.push_back(p.assign(path).append(fileinfo.name));
- // filesname存放文件名
- filesname.push_back(fileinfo.name);
- } while (_findnext(hFile, &fileinfo) == 0); // _findnext若匹配成功返回0,不成功返回-1
- _findclose(hFile);
- }
- }
3)设计一个getNumber函数,用于获取表格B中的号码信息,用于后期匹配。
- // 获取数字表
- vector
getNumber(string sheetpath) - {
- vector
numbers; - ifstream infile(sheetpath);
- string str;
- // 一行行读取
- while (getline(infile, str))
- {
- string temp = str.substr(0, 11);
- numbers.push_back(temp.c_str());
- }
- // 关闭
- infile.close();
- return numbers;
- }
4)设计一个copyFile函数,用于将文件M拷贝到另一路径中。
- // 复制文件
- void copyFile(char* tfrom, char* tto)
- {
- // 打开
- FILE* fpread = fopen(tfrom, "rb"); // 读
- FILE* fpwrite = fopen(tto, "wb"); // 写
- if (fpread == NULL) {
- cout << "error: read error." << endl;
- return;
- }
- if (fpwrite == NULL) {
- cout << "error: write error." << endl;
- return;
- }
- // 读写操作
- char* p;
- p = (char*)malloc(sizeof(char)); // 为指针申请内存空间
- while (!feof(fpread)) { // feof()检测光标后是否还有内容 没有则返回非0
- fread(p, sizeof(char), 1, fpread);
- fwrite(p, sizeof(char), 1, fpwrite);
- }
- if (p != NULL) {
- free(p);
- p = NULL;
- }
- // 关闭
- fclose(fpread);
- fclose(fpwrite);
- return;
- }
5)设计一个isMatch函数,用于匹配。如果你有自己其他的匹配需求,可以更改该函数。我这里只进行了一个去空格和寻找的操作。
- // 匹配字符串
- bool isMatch(string filename, vector
sheet) - {
- // 去除空格
- int i = int(filename.find(" ", 0));
- while (i != string::npos)
- {
- filename.replace(i, 1, "");
- i = int(filename.find(" ", 0));
- }
- // 取前11位号码
- string number = filename.substr(0, 11);
- // 寻找是否在库中
- vector
::iterator it = find(sheet.begin(), sheet.end(), number); - if (it == sheet.end())
- return false;
- else
- return true;
- }
6)用identifyFiles函数将上述功能简单封装一下。若输出文件夹不存在,创建一个;获取符合要求的文件的信息;获取表格B的号码;循环匹配,匹配成功,执行拷贝。
- // 识别文件
- void identifyFiles(std::string from, std::string to, std::string sheetpath, std::string suffix)
- {
- vector
files; - vector
filesname; - // 如果文件夹不存在,则创建
- if (_access(to.c_str(), 0) == -1)
- int re = _mkdir(to.c_str());
- // 获取符合要求文件的信息
- getFiles(from, files, filesname, suffix);
- // 获取数字表
- vector
numbers = getNumber(sheetpath); - // 识别
- int size = int(files.size());
- char* tf = new char[256];
- char* tn = new char[256];
- std::string target;
- for (int i = 0; i < size; i++)
- {
- // 若匹配成功则拷贝,失败则跳过
- if (isMatch(filesname[i], numbers))
- {
- target = to + filesname[i];
- strcpy(tf, files[i].c_str());
- strcpy(tn, target.c_str());
- copyFile(tf, tn);
- }
- }
- // 释放指针
- if (tn != NULL) {
- free(tn);
- tn = NULL;
- }
- if (tf != NULL) {
- free(tf);
- tf = NULL;
- }
- return;
- }
7)以上就是该功能实现的整个思路。
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #pragma warning(disable:4996)
- using namespace std;
-
- // 匹配字符串
- bool isMatch(string filename, vector
sheet) - {
- // 去除空格
- int i = int(filename.find(" ", 0));
- while (i != string::npos)
- {
- filename.replace(i, 1, "");
- i = int(filename.find(" ", 0));
- }
- // 取前11位号码
- string number = filename.substr(0, 11);
- // 寻找是否在库中
- vector
::iterator it = find(sheet.begin(), sheet.end(), number); - if (it == sheet.end())
- return false;
- else
- return true;
- }
-
- // 复制文件
- void copyFile(char* tfrom, char* tto)
- {
- // 打开
- FILE* fpread = fopen(tfrom, "rb"); // 读
- FILE* fpwrite = fopen(tto, "wb"); // 写
- if (fpread == NULL) {
- cout << "error: read error." << endl;
- return;
- }
- if (fpwrite == NULL) {
- cout << "error: write error." << endl;
- return;
- }
- // 读写操作
- char* p;
- p = (char*)malloc(sizeof(char)); // 为指针申请内存空间
- while (!feof(fpread)) { // feof()检测光标后是否还有内容 没有则返回非0
- fread(p, sizeof(char), 1, fpread);
- fwrite(p, sizeof(char), 1, fpwrite);
- }
- if (p != NULL) {
- free(p);
- p = NULL;
- }
- // 关闭
- fclose(fpread);
- fclose(fpwrite);
- return;
- }
-
- // 获取目标文件夹下目标文件信息
- void getFiles(std::string path, vector
& files, vector& filesname, std::string suffix) - {
- intptr_t hFile = 0;
- struct _finddata_t fileinfo;
- string p;
- // 寻找当前文件夹下后缀为mp3的文件
- if ((hFile = _findfirst(p.assign(path).append(suffix).c_str(), &fileinfo)) != -1) {
- do {
- // files存放文件全路径
- files.push_back(p.assign(path).append(fileinfo.name));
- // filesname存放文件名
- filesname.push_back(fileinfo.name);
- } while (_findnext(hFile, &fileinfo) == 0); // _findnext若匹配成功返回0,不成功返回-1
- _findclose(hFile);
- }
- }
-
- // 获取数字表
- vector
getNumber(string sheetpath) - {
- vector
numbers; - ifstream infile(sheetpath);
- string str;
- // 一行行读取
- while (getline(infile, str))
- {
- string temp = str.substr(0, 11);
- numbers.push_back(temp.c_str());
- }
- // 关闭
- infile.close();
- return numbers;
- }
-
- // 识别文件
- void identifyFiles(std::string from, std::string to, std::string sheetpath, std::string suffix)
- {
- vector
files; - vector
filesname; - // 如果文件夹不存在,则创建
- if (_access(to.c_str(), 0) == -1)
- int re = _mkdir(to.c_str());
- // 获取符合要求文件的信息
- getFiles(from, files, filesname, suffix);
- // 获取数字表
- vector
numbers = getNumber(sheetpath); - // 识别
- int size = int(files.size());
- char* tf = new char[256];
- char* tn = new char[256];
- std::string target;
- for (int i = 0; i < size; i++)
- {
- // 若匹配成功则拷贝,失败则跳过
- if (isMatch(filesname[i], numbers))
- {
- target = to + filesname[i];
- strcpy(tf, files[i].c_str());
- strcpy(tn, target.c_str());
- copyFile(tf, tn);
- }
- }
- // 释放指针
- if (tn != NULL) {
- free(tn);
- tn = NULL;
- }
- if (tf != NULL) {
- free(tf);
- tf = NULL;
- }
- return;
- }
-
- int main()
- {
- string from = "C:\\Users\\Administrator\\Desktop\\current\\";
- string to = "C:\\Users\\Administrator\\Desktop\\target\\";
- string sheetpath= "C:\\Users\\Administrator\\Desktop\\current\\test.txt";
- cout << "start:" << endl;
- cout << " from:" << from << endl;
- cout << " to:" << to << endl;
- cout << " dictionary:" << sheetpath << endl;
- // 识别文件
- identifyFiles(from, to, sheetpath, "\\*.mp3");
- cout << "end." << endl;
- return 0;
- }
在测试案例中,我创建了一些mp3文件,并仿照需求进行命名,test.txt作为表格B。实测下来,getFiles函数可以做到只存储特设后缀的文件信息,并且匹配功能也能成功适应带空格的命名情况。
如果函数有什么可以改进完善的地方,非常欢迎大家指出,一同进步何乐而不为呢~
如果文章帮助到你了,可以点个赞让我知道,我会很快乐~加油!