记录一个需求:在一个C++项目中,如果输入的路径是一个文件夹,那么把当前路径中的所有文件进行处理,如果是一个具体的文件,就直接处理一个文件。
windows
#include <iostream>
#ifdef WIN32
#include <Windows.h>
#else
#endif
#include <tchar.h>
#include <string>
#include <vector>
#include <fstream>
#ifdef WIN32
std::wstring winput_path = L"";//GetFileAttributes参数必须是宽字符字面量
for (char c : input_path) {
winput_path += wchar_t(c);//将string类型的路径一个字符一个字符的变成wstring
}
DWORD attributes = GetFileAttributes(winput_path.c_str());//获取当前文件的状态值,DWORD的二进制的每一位代表对应的文件状态
if (attributes & FILE_ATTRIBUTE_DIRECTORY) {//和FILE_ATTRIBUTE_DIRECTORY进行按位与运算,FILE_ATTRIBUTE_DIRECTORY只有代表当前路径是文件夹的那位是1,所以这部判断了当前路径是否是文件夹
//下面的代码获取了当前文件夹内的所有文件名,并且存到filename这个vector<string>中
WIN32_FIND_DATA findFileData;
std::string _input_path = input_path + std::string("\\*");
int buffersize = MultiByteToWideChar(CP_UTF8, 0, _input_path.c_str(), -1, NULL, 0);
wchar_t* wideString = new wchar_t[buffersize];
MultiByteToWideChar(CP_UTF8, 0, _input_path.c_str(), -1, wideString, buffersize);
LPCWSTR path = wideString;
HANDLE hFind = FindFirstFileW(path, &findFileData);
std::vector<std::string> fileName;
do {
if (findFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
//now this file is a directory
//同上,这步判断是否在文件夹中存在文件夹
continue;
}
std::wstring wname(findFileData.cFileName);
std::string sname(wname.begin(), wname.end());
fileName.push_back(sname);
} while (FindNextFile(hFind, &findFileData));
FindClose(hFind);
delete wideString;
for (auto item = fileName.begin(); item != fileName.end(); item++) {
//将文件名写到result.txt中
std::ofstream outputfile;
outputfile.open("result.txt", ios::app);
outputfile << (*item) + '\t';
outputfile.close();
//向__do__job函数传参,c风格字符串形式
char* output = __do_job(handle, (input_path + '\\' + *item).c_str(), language.c_str(), stitch);
delete[] output;
}
}
else {
char* output = __do_job(handle, input_path.c_str(), language.c_str(), stitch);
}
因为需要可移植,现在只完成了如何在windows上完成,后面再写如何在Linux上完成。
Linux版本
#include <stdio.h>
#include <dirent.h>
#include <sys/stat.h>
#include <string>
#include <vector>
#include <iostream>
using namespace std;
int main(){
string input_path = "...";
struct stat pathInfo;
vector<string> fileName;
if (stat(input_path.c_str(), &pathInfo) != 0) {
fprintf(stderr, "please check input path:%s");
return -1;
}
if (S_ISDIR(pathInfo.st_mode)) {
DIR* dir = opendir(input_path.c_str());
if (dir != NULL) {
struct dirent* entry;
//std::vector<std::string> fileName;
while ((entry = readdir(dir))) {
std::string entryName = entry->d_name;
std::string fullPath = input_path + "/" + entryName;
if (entryName != "." && entryName != "..") {
struct stat fileInfo;
if (stat(fullPath.c_str(), &fileInfo)==0) {
if (S_ISREG(fileInfo.st_mode))
fileName.push_back(entryName);
}
}
}
}
}
for(auto item=fileName.begin();item!=fileName.end();item++){
//cout << *item << endl;
fprintf(stdout,"%s\n",(*item).c_str());
}
return 0;
}
总体思路是一致的,区别在于linux中大部分使用dirent指针来作为文件句柄的角色。readdir()函数是在使用当前的句柄读取该目录下的下一个文件。stat是表示文件属性的数据结构。stat()函数,读取成功返回0,失败返回-1。S_ISREG()判断当前路径是否是一个普通文件。
句柄是什么?
在计算机编程中,句柄(Handle)是一种抽象数据类型,用于引用或标识特定资源或对象,如文件、内存块、窗口、设备等。句柄是一种管理和操作资源的方式,它允许程序访问和控制这些资源,而无需了解底层实现细节。
句柄通常是一个整数或指针,它在程序中用于唯一标识资源或对象。句柄的具体类型和用法取决于操作系统和编程语言。以下是一些常见的句柄类型和用途:
文件句柄: 用于标识打开的文件。文件句柄允许程序读取、写入、关闭和操作文件。
内存句柄: 用于管理动态分配的内存块。内存句柄允许程序分配、释放和操作内存。
窗口句柄: 用于标识图形用户界面 (GUI) 应用程序中的窗口。窗口句柄允许程序操控和显示窗口。
设备句柄: 用于访问硬件设备,如打印机、键盘、鼠标等。设备句柄允许程序与设备进行通信。
线程句柄: 用于标识操作系统中的线程。线程句柄允许程序创建、启动、停止和管理线程。
进程句柄: 用于标识操作系统中的进程。进程句柄允许程序创建、启动、终止和通信进程。
句柄的主要优点是它们提供了一种抽象层,隐藏了资源管理的底层复杂性。程序可以通过句柄来引用资源,而不必关心资源的实际物理或逻辑位置。这使得资源管理更加安全和可控,同时提供了更高的抽象级别,使编程更加方便。句柄还可以用于资源共享和访问控制,以确保多个程序可以协同使用资源而不会发生冲突。
个人理解:句柄类似于访问资源的一个接口,掩盖了底层的具体实现。