文件分类小助手

本文介绍了一个使用C++实现的程序,该程序能够自动将大量Excel文件按文件名中的地理位置信息进行分类,大大提升了工作效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

事情的起因是这样的,女朋友工作里面常常动则大几百个EXCEL文件,每个全来自不同省下面的市或区域,每个月总有那么几天要进行分类工作,所以就常常找花眼,一边百度巢湖是哪个省的,涿州是哪个省的,一边进行分类。而我当然也是常常被她拉起承担这种没技术的活。

这几天学了些C++里STL的东西,感觉很多事情已经很方便很简单了,所以想写个程序来帮着做这些重复性的工作,自动根据文件的名字对其所在省份进行分类。

首先上个效果图吧:

可以看到文件名字会有地理位置,然后根据其所在位置放入相应省份的文件夹。

具体做法:先是几个函数。

1、搜索当前路径下面的以.xls或.xlsx为结尾的文件,并加入链表。

头文件SearchDir.h

#ifndef _SEARCH_DIR_H
#define _SEARCH_DIR_H
#include <string>
#include <fstream>
#include <windows.h>
#include <list>
#include<iostream>
#endif

文件SearchDir.cpp

#include "SearchDir.h"
using namespace std;


list <string> & FindFileName(string route_temp, list<string> & filenames)
{  
	string filename;
	string route =route_temp;
	if (route.substr(route.length()-1) != "\\" )//检查要查找的路径名是否完整,在最后要加上'/'
	{
		route += "\\";
	}
	string route_copy = route;
	/*首先先扫描当前文件夹下的所有文件夹,并且加入文件夹的队列director_found */
	route +="*";
	WIN32_FIND_DATA Finddata;
	HANDLE hfile = FindFirstFile(route.c_str(), &Finddata);
	if(hfile != INVALID_HANDLE_VALUE)
		{
			do 
			{
				string  file_name = Finddata.cFileName;
				if (file_name.size() <= 4)
				{
					continue;
				}
				if (file_name.substr(file_name.size() - 5, file_name.size()) == ".xlsx"
					|| file_name.substr(file_name.size() - 4, file_name.size()) == ".xls")//是excel文件
				{
					filenames.push_back(file_name);
				}

			 
			
			} while (FindNextFile(hfile, &Finddata));
		}
	return filenames;
	
}

2、搜索一个我附加的文档,用来匹配   省份——地方,格式是下面这个样子的

前面是省份,后面是地方。其实逗逼了,这个格式省份多打了好多,后面可以看到,这完全是多余的。

SearchProvince.h

#ifndef _SEARCH_PROVINCE_H
#define _SEARCH_PROVINCE_H
#include <iostream>
#include <fstream>
#include <string>
#endif

SearchProvince.cpp

拿的别人的代码改了一点点

#include "SearchProvince.h"

using namespace std;


// 通过城市名字查找省份,主要是文件操作
string SearchProvince(string path, string cityname)
{
	string provincename;
	ifstream fin;
	fin.open(path, ios_base::in);
	if(!fin.is_open()) //打开原始文件1.txt,将其赋给了文件指针fp1,并判断文件指针fp1是否为NULL
	{
		cout << " province.txt 打开失败!请确保文件存在!\n";
		return "No file!";
	}
	string strpair;
	while (true)
	{
		getline(fin, strpair);
		if (fin.eof())
		{
			fin.close();
			return "Not found!";
		}
		if (strpair.find(cityname) != strpair.npos)
		{
			provincename = strpair.substr(0, strpair.find_first_of(" "));
			break;
		}
	}
	
	if (provincename.empty())
	{
		fin.close();
		return "Error!";
	}
	fin.close();
	return provincename;
}

3、移动文件操作

MoveFile.h

#ifndef _MOVE_FILE_H
#define _MOVE_FILE_H
#include <Windows.h>
#include <Shlwapi.h>
#include <string>
#include <iostream>
#include <direct.h>
#endif

MoveFile.cpp

#include "MoveFile.h"

using namespace std;

#define SIZEOFBUFFER 256*1024L /* 缓冲区大小,默认为256KB */

long filesize(FILE *stream)
{
	long curpos, length;
	curpos = ftell(stream);
	fseek(stream, 0L, SEEK_END);
	length = ftell(stream);
	fseek(stream, curpos, SEEK_SET);
	return length;
}

int copyfile(const char* src,const char* dest)
{
	FILE *fp1,*fp2;
	int fsize,factread;
	static unsigned char buffer[SIZEOFBUFFER];

	fp1=fopen(src,"rb");
	fp2=fopen(dest,"wb+");
	if (!fp1 || !fp2) return 0;
	for (fsize=filesize(fp1);fsize>0;fsize-=SIZEOFBUFFER)
	{
		factread=fread(buffer,1,SIZEOFBUFFER,fp1);
		fwrite(buffer,factread,1,fp2);
	}
	fclose(fp1);
	fclose(fp2);
	remove(src);
	return 1;
}

int Classify(string path, string dirname, string filename)
{
	string dirplace = path + "\\" + dirname;
	_mkdir(dirplace.data());
	
	string oldplace = path + "\\" + filename;
	string newplace = dirplace + "\\" + filename;
	if (!copyfile(oldplace.data(), newplace.data()))
	{
		cout << "文件" << filename << "移动失败" << endl;
		return 0;
	}
	cout << filename << "移入<" << dirname << ">" << endl;
	return 1;
 }

copyfile是直接拿的别人的代码来用的。搜到有网上说的windows.h里面定义的CreateDirectory()函数和MoveFile()函数都不起作用,我也没搞明白,就用了这个_mkdir()和别人写的copyfile()外加一个remove()了。
4、主程序

main.h

#ifndef _MAIN_H
#define _MAIN_H
#include <stdio.h>
#include <iostream>
#include <string>
#include <list>
#include <algorithm>
#include <iterator>
#include "SearchDir.h"
#include "SearchProvince.h"
#include "MoveFile.h"
#endif

main.cpp

#include "main.h"


using namespace std;

// 函数声明
list <string> & FindFileName(string, list<string> &);
string SearchProvince(string, string);
int Classify(string, string, string);

const string Path = ".\\";   // 当前文件夹


void classify(string filename)
{
	string province;
	if (filename.size() > 27)
	{
		province = SearchProvince(Path + "province.txt", filename.substr(42, 4));	// 这里的42是我去数出来的,不够智能,对其它文件适用性不好
	}
	if (!province.empty() && province != "No file!"
		&& province != "Not found!" && province != "Error!")
	{
		Classify(Path, province, filename);
	}
	
}

// 声明
void Attention()
{
	cout << "文件分类助手1.0" << endl;
	cout << "===========================================================================" << endl;
	cout << "重要说明:" << endl;
	cout << "1、此程序只针对后缀名.xls及.xlsx进行分类" << endl;
	cout << "2、请确保文件名符合一定格式,地理位置名词目前仅支持出现在特定位置" << endl;
	cout << "3、当文件无法进行分类时,请自行对province.txt文件进行增加内容,格式为\"文件夹名\" \"关键字\"" << endl;
	cout << "===========================================================================" << endl;
	cout << "有任何问题,请联系作者" << endl;
	cout << "你滴工作可以更轻松滴!" << endl;
	cout << "===========================================================================" << endl;
}

int main(int argc,char** argv)
{
	Attention();
	list <string> filenames;
	filenames = FindFileName(Path, filenames);//要扫描的文件夹,这是放在当前目录下的文件夹
	int num=filenames.size();
	cout<<"总文件数"<<num<<endl;
	for_each(filenames.begin(), filenames.end(), classify);
	filenames.clear();
	filenames = FindFileName(Path, filenames);
	cout << "已分类" << num - filenames.size() << "个,未分类" << filenames.size() << "个" << endl;
	system("pause");
	return 0;
}	// 这里的42是我去数出来的,不够智能,对其它文件适用性不好
	}
	if (!province.empty() && province != "No file!"
		&& province != "Not found!" && province != "Error!")
	{
		Classify(Path, province, filename);
	}
	
}

// 声明
void Attention()
{
	cout << "文件分类助手1.0" << endl;
	cout << "===========================================================================" << endl;
	cout << "重要说明:" << endl;
	cout << "1、此程序只针对后缀名.xls及.xlsx进行分类" << endl;
	cout << "2、请确保文件名符合一定格式,地理位置名词目前仅支持出现在特定位置" << endl;
	cout << "3、当文件无法进行分类时,请自行对province.txt文件进行增加内容,格式为\"文件夹名\" \"关键字\"" << endl;
	cout << "===========================================================================" << endl;
	cout << "有任何问题,请联系作者" << endl;
	cout << "你滴工作可以更轻松滴!" << endl;
	cout << "===========================================================================" << endl;
}

int main(int argc,char** argv)
{
	Attention();
	list <string> filenames;
	filenames = FindFileName(Path, filenames);//要扫描的文件夹,这是放在当前目录下的文件夹
	int num=filenames.size();
	cout<<"总文件数"<<num<<endl;
	for_each(filenames.begin(), filenames.end(), classify);
	filenames.clear();
	filenames = FindFileName(Path, filenames);
	cout << "已分类" << num - filenames.size() << "个,未分类" << filenames.size() << "个" << endl;
	system("pause");
	return 0;
}


以上是全部代码了。

最主要存在的问题是, 文件名中地方名必须出现在指定位置,否则程序找不到正确的名字。下一步是看如何能想出更智能的方法,适用于不同的命名格式。

各位有什么好的主意没有?

最后上一下程序下载地址:http://download.csdn.net/detail/top_along/7351399
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值