事情的起因是這樣的,女朋友工作裏面常常動則大幾百個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 << "重要說明:" << endl;
cout << "1、此程序只針對後綴名.xls及.xlsx進行分類" << endl;
cout << "2、請確保文件名符合一定格式,地理位置名詞目前僅支持出現在特定位置" << endl;
cout << "3、當文件無法進行分類時,請自行對province.txt文件進行增加內容,格式爲\"文件夾名\" \"關鍵字\"" << endl;
cout << "===========================================================================" << endl;
cout << "有任何問題,請聯繫作者" << endl;
cout << "作者:top_along 郵箱:[email protected]" << 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