• C++-筛选文件夹中符合要求的文件并拷贝出来(以手机号码查找为例)


    作者:翟天保Steven
    版权声明:著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处

    场景需求

           在日常工作中,必然会和各类文件打交道,如何高效地操作处理文件是提高工作效率的关键。Excel、VB、Python等等用好了,都可以将傻瓜操作(批量复制粘贴、筛选查找等)自动化,仅需秒级时间,即可完成他人小时级时间的工作量,剩下的时间至于是摸鱼还是自主学习,就看个人了。由此可见,高效的工作方法选对了是多么重要。

          本文所要实现的需求:有一文件夹A,大概有千级往上数量的录音文件,每个录音文件名格式为“手机号码+乱码.xxx”;手头另有一号码表格B,存放了200个左右的11位手机号码。要求将文件夹A中号码与表格B号码匹配的录音,拷贝到另一文件夹C中。

           如果用EXCEL,可以借助VLOOKUP,完成筛选,再用Bat的copy指令,完成拷贝操作。(方法多种多样,有其他思路的欢迎评论区留言,一同交流学习)

           那如何用C++实现,本文将进行详细的讲解,提供源码和简易测试代码。(实现方法同样多种多样,本文仅用了一种方案,仅供参考)

    解决思路

           要想完成该功能,可以拆分一下各个子功能。

    • 第一步要做的是将文件夹A中后缀为xxx的文件先提取出来。
    • 第二步是将表格B中的号码提取出来。
    • 第三步是匹配,也是关键步骤。将A中与B匹配的录音筛选出来,只有满足要求才能拷贝,其他的直接跳过。该步骤也是大家可以自定义匹配规则的一步,根据自己需求设计。

    具体实现

           1)我们将文件夹A的路径用字符串from存储下来,文件夹C的路径用字符串to存储下来,同时定义一个表格B的路径。

    1. string from = "C:\\Users\\Administrator\\Desktop\\current\\";
    2. string to = "C:\\Users\\Administrator\\Desktop\\target\\";
    3. string sheetpath= "C:\\Users\\Administrator\\Desktop\\current\\test.txt";

           2)设计一个getFiles函数,用于获取目标文件夹下目标文件信息,并存放在vector中。

    1. // 获取目标文件夹下目标文件信息
    2. void getFiles(std::string path, vector& files, vector& filesname, std::string suffix)
    3. {
    4. intptr_t hFile = 0;
    5. struct _finddata_t fileinfo;
    6. string p;
    7. // 寻找当前文件夹下后缀为mp3的文件
    8. if ((hFile = _findfirst(p.assign(path).append(suffix).c_str(), &fileinfo)) != -1) {
    9. do {
    10. // files存放文件全路径
    11. files.push_back(p.assign(path).append(fileinfo.name));
    12. // filesname存放文件名
    13. filesname.push_back(fileinfo.name);
    14. } while (_findnext(hFile, &fileinfo) == 0); // _findnext若匹配成功返回0,不成功返回-1
    15. _findclose(hFile);
    16. }
    17. }

           3)设计一个getNumber函数,用于获取表格B中的号码信息,用于后期匹配。

    1. // 获取数字表
    2. vector getNumber(string sheetpath)
    3. {
    4. vector numbers;
    5. ifstream infile(sheetpath);
    6. string str;
    7. // 一行行读取
    8. while (getline(infile, str))
    9. {
    10. string temp = str.substr(0, 11);
    11. numbers.push_back(temp.c_str());
    12. }
    13. // 关闭
    14. infile.close();
    15. return numbers;
    16. }

           4)设计一个copyFile函数,用于将文件M拷贝到另一路径中。

    1. // 复制文件
    2. void copyFile(char* tfrom, char* tto)
    3. {
    4. // 打开
    5. FILE* fpread = fopen(tfrom, "rb"); // 读
    6. FILE* fpwrite = fopen(tto, "wb"); // 写
    7. if (fpread == NULL) {
    8. cout << "error: read error." << endl;
    9. return;
    10. }
    11. if (fpwrite == NULL) {
    12. cout << "error: write error." << endl;
    13. return;
    14. }
    15. // 读写操作
    16. char* p;
    17. p = (char*)malloc(sizeof(char)); // 为指针申请内存空间
    18. while (!feof(fpread)) { // feof()检测光标后是否还有内容 没有则返回非0
    19. fread(p, sizeof(char), 1, fpread);
    20. fwrite(p, sizeof(char), 1, fpwrite);
    21. }
    22. if (p != NULL) {
    23. free(p);
    24. p = NULL;
    25. }
    26. // 关闭
    27. fclose(fpread);
    28. fclose(fpwrite);
    29. return;
    30. }

           5)设计一个isMatch函数,用于匹配。如果你有自己其他的匹配需求,可以更改该函数。我这里只进行了一个去空格和寻找的操作。

    1. // 匹配字符串
    2. bool isMatch(string filename, vector sheet)
    3. {
    4. // 去除空格
    5. int i = int(filename.find(" ", 0));
    6. while (i != string::npos)
    7. {
    8. filename.replace(i, 1, "");
    9. i = int(filename.find(" ", 0));
    10. }
    11. // 取前11位号码
    12. string number = filename.substr(0, 11);
    13. // 寻找是否在库中
    14. vector::iterator it = find(sheet.begin(), sheet.end(), number);
    15. if (it == sheet.end())
    16. return false;
    17. else
    18. return true;
    19. }

           6)用identifyFiles函数将上述功能简单封装一下。若输出文件夹不存在,创建一个;获取符合要求的文件的信息;获取表格B的号码;循环匹配,匹配成功,执行拷贝。

    1. // 识别文件
    2. void identifyFiles(std::string from, std::string to, std::string sheetpath, std::string suffix)
    3. {
    4. vector files;
    5. vector filesname;
    6. // 如果文件夹不存在,则创建
    7. if (_access(to.c_str(), 0) == -1)
    8. int re = _mkdir(to.c_str());
    9. // 获取符合要求文件的信息
    10. getFiles(from, files, filesname, suffix);
    11. // 获取数字表
    12. vector numbers = getNumber(sheetpath);
    13. // 识别
    14. int size = int(files.size());
    15. char* tf = new char[256];
    16. char* tn = new char[256];
    17. std::string target;
    18. for (int i = 0; i < size; i++)
    19. {
    20. // 若匹配成功则拷贝,失败则跳过
    21. if (isMatch(filesname[i], numbers))
    22. {
    23. target = to + filesname[i];
    24. strcpy(tf, files[i].c_str());
    25. strcpy(tn, target.c_str());
    26. copyFile(tf, tn);
    27. }
    28. }
    29. // 释放指针
    30. if (tn != NULL) {
    31. free(tn);
    32. tn = NULL;
    33. }
    34. if (tf != NULL) {
    35. free(tf);
    36. tf = NULL;
    37. }
    38. return;
    39. }

           7)以上就是该功能实现的整个思路。

    C++完整代码及测试案例

    1. #include
    2. #include
    3. #include
    4. #include
    5. #include
    6. #include
    7. #include
    8. #include
    9. #include
    10. #include
    11. #include
    12. #pragma warning(disable:4996)
    13. using namespace std;
    14. // 匹配字符串
    15. bool isMatch(string filename, vector sheet)
    16. {
    17. // 去除空格
    18. int i = int(filename.find(" ", 0));
    19. while (i != string::npos)
    20. {
    21. filename.replace(i, 1, "");
    22. i = int(filename.find(" ", 0));
    23. }
    24. // 取前11位号码
    25. string number = filename.substr(0, 11);
    26. // 寻找是否在库中
    27. vector::iterator it = find(sheet.begin(), sheet.end(), number);
    28. if (it == sheet.end())
    29. return false;
    30. else
    31. return true;
    32. }
    33. // 复制文件
    34. void copyFile(char* tfrom, char* tto)
    35. {
    36. // 打开
    37. FILE* fpread = fopen(tfrom, "rb"); // 读
    38. FILE* fpwrite = fopen(tto, "wb"); // 写
    39. if (fpread == NULL) {
    40. cout << "error: read error." << endl;
    41. return;
    42. }
    43. if (fpwrite == NULL) {
    44. cout << "error: write error." << endl;
    45. return;
    46. }
    47. // 读写操作
    48. char* p;
    49. p = (char*)malloc(sizeof(char)); // 为指针申请内存空间
    50. while (!feof(fpread)) { // feof()检测光标后是否还有内容 没有则返回非0
    51. fread(p, sizeof(char), 1, fpread);
    52. fwrite(p, sizeof(char), 1, fpwrite);
    53. }
    54. if (p != NULL) {
    55. free(p);
    56. p = NULL;
    57. }
    58. // 关闭
    59. fclose(fpread);
    60. fclose(fpwrite);
    61. return;
    62. }
    63. // 获取目标文件夹下目标文件信息
    64. void getFiles(std::string path, vector& files, vector& filesname, std::string suffix)
    65. {
    66. intptr_t hFile = 0;
    67. struct _finddata_t fileinfo;
    68. string p;
    69. // 寻找当前文件夹下后缀为mp3的文件
    70. if ((hFile = _findfirst(p.assign(path).append(suffix).c_str(), &fileinfo)) != -1) {
    71. do {
    72. // files存放文件全路径
    73. files.push_back(p.assign(path).append(fileinfo.name));
    74. // filesname存放文件名
    75. filesname.push_back(fileinfo.name);
    76. } while (_findnext(hFile, &fileinfo) == 0); // _findnext若匹配成功返回0,不成功返回-1
    77. _findclose(hFile);
    78. }
    79. }
    80. // 获取数字表
    81. vector getNumber(string sheetpath)
    82. {
    83. vector numbers;
    84. ifstream infile(sheetpath);
    85. string str;
    86. // 一行行读取
    87. while (getline(infile, str))
    88. {
    89. string temp = str.substr(0, 11);
    90. numbers.push_back(temp.c_str());
    91. }
    92. // 关闭
    93. infile.close();
    94. return numbers;
    95. }
    96. // 识别文件
    97. void identifyFiles(std::string from, std::string to, std::string sheetpath, std::string suffix)
    98. {
    99. vector files;
    100. vector filesname;
    101. // 如果文件夹不存在,则创建
    102. if (_access(to.c_str(), 0) == -1)
    103. int re = _mkdir(to.c_str());
    104. // 获取符合要求文件的信息
    105. getFiles(from, files, filesname, suffix);
    106. // 获取数字表
    107. vector numbers = getNumber(sheetpath);
    108. // 识别
    109. int size = int(files.size());
    110. char* tf = new char[256];
    111. char* tn = new char[256];
    112. std::string target;
    113. for (int i = 0; i < size; i++)
    114. {
    115. // 若匹配成功则拷贝,失败则跳过
    116. if (isMatch(filesname[i], numbers))
    117. {
    118. target = to + filesname[i];
    119. strcpy(tf, files[i].c_str());
    120. strcpy(tn, target.c_str());
    121. copyFile(tf, tn);
    122. }
    123. }
    124. // 释放指针
    125. if (tn != NULL) {
    126. free(tn);
    127. tn = NULL;
    128. }
    129. if (tf != NULL) {
    130. free(tf);
    131. tf = NULL;
    132. }
    133. return;
    134. }
    135. int main()
    136. {
    137. string from = "C:\\Users\\Administrator\\Desktop\\current\\";
    138. string to = "C:\\Users\\Administrator\\Desktop\\target\\";
    139. string sheetpath= "C:\\Users\\Administrator\\Desktop\\current\\test.txt";
    140. cout << "start:" << endl;
    141. cout << " from:" << from << endl;
    142. cout << " to:" << to << endl;
    143. cout << " dictionary:" << sheetpath << endl;
    144. // 识别文件
    145. identifyFiles(from, to, sheetpath, "\\*.mp3");
    146. cout << "end." << endl;
    147. return 0;
    148. }

    测试效果

           在测试案例中,我创建了一些mp3文件,并仿照需求进行命名,test.txt作为表格B。实测下来,getFiles函数可以做到只存储特设后缀的文件信息,并且匹配功能也能成功适应带空格的命名情况。

           如果函数有什么可以改进完善的地方,非常欢迎大家指出,一同进步何乐而不为呢~

           如果文章帮助到你了,可以点个赞让我知道,我会很快乐~加油!

  • 相关阅读:
    使用Android studio,安卓手机编译安装yolov8部署ncnn,频繁出现编译错误
    CF1539 D. PriceFixed
    Spring-IoC源码分析
    华为OD机试 - 真正的密码 - 数据结构list(Java 2023 B卷 100分)
    ESP32 使用 LVGL 的简单介绍(ESP32 for Arduino)
    Redis源码阅读02-数据结构sds
    【javaEE】多线程初阶(Part6 阻塞队列)
    C++面试宝典设计模式之单例模式
    Java 版 spring cloud 工程系统管理 +二次开发 工程项目管理系统源码
    GESP-9月
  • 原文地址:https://blog.csdn.net/zhaitianbao/article/details/126930605