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

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

场景需求

      在日常工作中,必然会和各类文件打交道,如何高效地操作处理文件是提高工作效率的关键。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的路径。

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<std::string>& files, vector<std::string>& 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<string> getNumber(string sheetpath)
{
  vector<string> 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<string> 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<string>::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<std::string> files;
  vector<std::string> filesname;
  // 如果文件夹不存在,则创建
  if (_access(to.c_str(), 0) == -1)
    int re = _mkdir(to.c_str());
  // 获取符合要求文件的信息
  getFiles(from, files, filesname, suffix);
  // 获取数字表
  vector<string> 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)以上就是该功能实现的整个思路。

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

#include <iostream>
#include <stdlib.h>
#include <io.h>
#include <vector>
#include <stdio.h>
#include <string>
#include <cstring>
#include <vector>
#include <sstream>
#include <fstream>
#include <direct.h>
#pragma warning(disable:4996)
using namespace std;
// 匹配字符串
bool isMatch(string filename, vector<string> 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<string>::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<std::string>& files, vector<std::string>& 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<string> getNumber(string sheetpath)
{
  vector<string> 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<std::string> files;
  vector<std::string> filesname;
  // 如果文件夹不存在,则创建
  if (_access(to.c_str(), 0) == -1)
    int re = _mkdir(to.c_str());
  // 获取符合要求文件的信息
  getFiles(from, files, filesname, suffix);
  // 获取数字表
  vector<string> 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函数可以做到只存储特设后缀的文件信息,并且匹配功能也能成功适应带空格的命名情况。


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


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

相关文章
|
1月前
|
C++
C/C++给文件加crc校验
C/C++给文件加crc校验
22 1
|
2月前
|
存储 C++
基于C++的简易文件压缩与解压缩工具设计与实现
基于C++的简易文件压缩与解压缩工具设计与实现
16 3
|
2月前
|
Linux 编译器 C++
C/C++性能优化:从根本上消除拷贝操作的浪费
C/C++性能优化:从根本上消除拷贝操作的浪费
56 0
|
监控 算法 编译器
C++通过libssh2库获取 SFTP指定文件的最后修改时间的方法
C++通过libssh2库获取 SFTP指定文件的最后修改时间的方法
30 0
|
2月前
|
安全 算法 程序员
【C/C++ 文件操作】深入理解C语言中的文件锁定机制
【C/C++ 文件操作】深入理解C语言中的文件锁定机制
46 0
|
2月前
|
JSON 安全 JavaScript
怎么保护苹果手机移动应用程序ipa中文件安全?
怎么保护苹果手机移动应用程序ipa中文件安全?
22 1
|
2月前
|
Unix 编译器 Linux
【计算机基础 ELF文件】深入探索ELF文件:C++编程中的关键组成部分
【计算机基础 ELF文件】深入探索ELF文件:C++编程中的关键组成部分
53 0
|
2月前
|
Linux 数据处理 C++
Linux系统编程 C/C++ 以及Qt 中的零拷贝技术: 从底层原理到高级应用(一)
Linux系统编程 C/C++ 以及Qt 中的零拷贝技术: 从底层原理到高级应用
81 0
|
2月前
|
存储 Linux API
Linux系统编程 C/C++ 以及Qt 中的零拷贝技术: 从底层原理到高级应用(三)
Linux系统编程 C/C++ 以及Qt 中的零拷贝技术: 从底层原理到高级应用
34 1
|
2月前
|
消息中间件 Linux 数据处理
Linux系统编程 C/C++ 以及Qt 中的零拷贝技术: 从底层原理到高级应用(二)
Linux系统编程 C/C++ 以及Qt 中的零拷贝技术: 从底层原理到高级应用
37 1