C++如何获取当前路径下所有文件的文件名

本文介绍如何使用C++获取当前程序所在文件夹的路径,并递归地找到指定目录下及其子目录中所有文件的文件名。通过具体代码示例,展示了获取绝对路径和相对路径的方法。

C++如何获取当前路径下所有文件的文件名

今天我遇到了这样一个任务:要求编写一个程序,统计和这个程序在同一目录下(及其子目录)所有文件的单词数。统计单词数十分倒不是太难,倒是找出同一目录下的所有文件,是我从来没有接触过的。仔细分析,这个问题其实包含两个小问题:

1. 如何获取当前程序所在文件夹的路径
2. 如何给定一个路径,递归地找到其中(包括子目录)所有文件的文件名(相对路径)

那我们就依次解决这两个问题。
.
.

1. 如何获取当前程序所在文件夹的路径

.
.
解决这个问题只需要一个简单的函数即可(需要包含一个输入输出库):

#include <io.h>
char *getcwd( char *buffer, int maxlen );

这个函数能够获取当前的工作目录,具体来说,它会将当前工作目录的绝对路径复制到参数buffer所指的内存空间中,参数maxlen为buffer的空间大小。
.
我们可以写一个程序来测试一下。

#include<iostream>
#include<io.h>
using namespace std;

#define MAX_PATH 80

int main()
{
char buffer[MAX_PATH];
getcwd(buffer, MAX_PATH);
cout << buffer << endl;
return 0;
}


.
运行成功!
.
.
.

2. 如何给定一个路径,递归地找到其中(包括子目录)所有文件的文件名(相对路径)

.
.
这里我使用了网上现成的代码,先附上链接
.
这里,他定义了一个函数(需要包含一个向量库,当然,还有我们在上一个问题里需要使用的输入输出库)

#include <io.h>
#include<vector>
void getFiles(string path, vector<string>& files);

它的用处是,给定一个文件目录path,然后找到其中所有(包括其子目录里)的文件,将文件名放入files中,files是一个字符串向量的引用类型。
.
具体的函数内容是这样的:

void getFiles( string path, vector<string>& files )  
{  
    //文件句柄  
    long   hFile   =   0;  
    //文件信息  
    struct _finddata_t fileinfo;  
    string p;  
    if((hFile = _findfirst(p.assign(path).append("\\*").c_str(),&fileinfo)) !=  -1)  
    {  
        do  
        {  
            //如果是目录,迭代之  
            //如果不是,加入列表  
            if((fileinfo.attrib &  _A_SUBDIR))  
            {  
                if(strcmp(fileinfo.name,".") != 0  &&  strcmp(fileinfo.name,"..") != 0)  
                    getFiles( p.assign(path).append("\\").append(fileinfo.name), files );  
            }  
            else  
            {  
                files.push_back(p.assign(path).append("\\").append(fileinfo.name) );  
            }  
        }while(_findnext(hFile, &fileinfo)  == 0);  
        _findclose(hFile);  
    }  
}

.
下面给出一个运用这个函数的例子:

#include<iostream>
#include<vector>
#include<io.h>
using namespace std;

#define MAX_PATH 80
void getFiles( string path, vector<string>& files );

int main()
{
vector<string> files;
char * filePath = “C:\Users\Star\Desktop\SoftTest”;
////获取该路径下的所有文件
getFiles(filePath, files);
char str[30];
int size = files.size();
for (int i = 0;i < size;i++)
{
cout<<files[i].c_str()<<endl;
}
return 0;
}


运行成功!
.
.
.

3. 组合以后的完整代码

.

#include<iostream>
#include<vector>
#include<io.h>
using namespace std;

#define MAX_PATH 80
void getFiles( string path, vector<string>& files );

int main()
{
vector<string> files;
char buffer[MAX_PATH];
getcwd(buffer, MAX_PATH);
char * filePath = buffer;
////获取该路径下的所有文件
getFiles(filePath, files );
char str[30];
int size = files.size();
for (int i = 0;i < size;i++)
{
cout<<files[i].c_str()<<endl;
}
return 0;
}

void getFiles( string path, vector<string>& files )
{
//文件句柄
long hFile = 0;
//文件信息
struct _finddata_t fileinfo;
string p;
if((hFile = _findfirst(p.assign(path).append("\*").c_str(),&fileinfo)) != -1)
{
do
{
//如果是目录,迭代之
//如果不是,加入列表
if((fileinfo.attrib & _A_SUBDIR))
{
if(strcmp(fileinfo.name,".") != 0 && strcmp(fileinfo.name,"…") != 0)
getFiles( p.assign(path).append("\").append(fileinfo.name), files );
}
else
{
files.push_back(p.assign(path).append("\").append(fileinfo.name) );
}
}while(_findnext(hFile, &fileinfo) == 0);
_findclose(hFile);
}
}

.
这段代码的运行结果和上面的运行结果相同,我就不给出运行结果了。
.
.
.

4.返回相对路径

.
之前的那种方法很好,不过唯一的缺点是,函数返回的都是绝对路径,如果想要改成相对路径,该怎么办呢?
.
.
我将代码进行了修改,具体做法是在getFile()函数中加入了一个path2参数,改进后的代码如下:
.

#include<iostream>
#include<vector>
#include<io.h>
using namespace std;

#define MAX_PATH 80
void getFiles( string path, string path2, vector<string>& files );

int main(){
vector<string> files;
char buffer[MAX_PATH];
getcwd(buffer, MAX_PATH);
string filePath;
filePath.assign(buffer).append("\");
////获取该路径下的所有文件
getFiles(filePath,"", files );
char str[30];
int size = files.size();
for (int i = 0;i < size;i++)
{
cout<<files[i].c_str()<<endl;
}
return 0;
}

void getFiles( string path, string path2, vector<string>& files )
{
//文件句柄
long hFile = 0;
//文件信息
struct _finddata_t fileinfo;
string p,p2;
if((hFile = _findfirst(p.assign(path).append(path2).append("*").c_str(),&fileinfo)) != -1)
{
do
{
//如果是目录,迭代之
//如果不是,加入列表
if((fileinfo.attrib & _A_SUBDIR))
{
if(strcmp(fileinfo.name,".") != 0 && strcmp(fileinfo.name,"…") != 0)
getFiles( p.assign(path).append("\"),p2.assign(fileinfo.name).append("\"), files );
}
else
{
files.push_back(p.assign(path2).append(fileinfo.name) ); //这一行可以给出相对路径
//files.push_back(p.assign(fileinfo.name) ); //这一行可以给出文件名
}
}while(_findnext(hFile, &fileinfo) == 0);
_findclose(hFile);
}
}

.
运行结果:

成功地给出了相对路径!!
.
.
也可以给出文件名:

.
.
.

<think>我们参考用户提供的引用内容,特别是引用[1]和引用[4]中关于获取目录下文件名的代码。 用户需求:在C++获取指定路径下所有文件文件名(不包括目录,只包括普通文件)。 注意:用户没有要求递归子目录,所以只获取指定目录下的文件。 有两种主要方法: 1. 使用C++17的<filesystem>库(跨平台,推荐) 2. 使用POSIX API(如opendir, readdir等,适用于Linux,Windows下可能不直接支持) 考虑到跨平台,我们优先使用C++17的filesystem库。但需要注意,在旧编译器上可能需要使用实验版本或Boost库。 根据引用[1]中的代码,使用了std::experimental::filesystem,这是C++17标准之前的实验版本。现在C++17已经正式支持,我们可以使用标准版本。 步骤: 1. 包含头文件:<filesystem> 2. 使用std::filesystem::directory_iterator遍历目录 3. 检查每个条目是否为普通文件(regular_file) 4. 获取文件名(可以包括路径,也可以只获取文件名部分) 注意:需要编译器支持C++17,并在编译时开启C++17标准。 下面我们提供两种方法: 方法一:使用C++17标准库(推荐) 方法二:使用POSIX(Linux/Unix)的dirent.h(如引用[4]) 用户可能还需要考虑是否包含隐藏文件,以及是否跳过"."和".."目录。 我们按照用户要求,只获取普通文件(不包括目录),并且跳过"."和".."(在filesystem中,directory_iterator默认不会返回"."和"..")。 方法一(C++17标准): 注意:在Visual Studio中,可能需要设置项目属性支持C++17;在g++或clang中,编译时需要加上-std=c++17。 代码示例: */ #include <iostream> #include <vector> #include <string> #include <filesystem> // C++17 标准头文件 namespace fs = std::filesystem; // 函数:获取指定路径下的所有文件名(只包括普通文件,不包括目录) // 参数:path - 目录路径 // 返回:std::vector<std::string> 包含所有文件名的向量(完整路径) std::vector<std::string> get_all_files_in_directory(const std::string& path) { std::vector<std::string> file_list; try { for (const auto& entry : fs::directory_iterator(path)) { if (entry.is_regular_file()) { // 获取文件的完整路径 file_list.push_back(entry.path().string()); } } } catch (const fs::filesystem_error& e) { std::cerr << "文件系统错误: " << e.what() << std::endl; } catch (const std::exception& e) { std::cerr << "标准异常: " << e.what() << std::endl; } catch (...) { std::cerr << "未知错误!" << std::endl; } return file_list; } // 如果只需要文件名(不包括路径),则可以使用entry.path().filename().string() /* 方法二:使用POSIX API(适用于Linux/Unix,Windows下可以使用MinGW等环境) 注意:Windows下原生API不同,这里使用dirent.h(需要确保在Windows下也有这个头文件,或者只在Linux下使用) 参考引用[4]的代码,但做一点调整:我们只获取普通文件,跳过目录和特殊文件。 代码示例: */ #ifdef _WIN32 // 在Windows上,我们也可以使用dirent.h,但需要额外配置,或者使用Windows API // 这里为了跨平台,我们仅在非Windows环境下使用dirent.h,Windows下使用上面的filesystem #else #include <dirent.h> #include <sys/types.h> #endif // 使用POSIX的版本(仅用于非Windows系统) #ifndef _WIN32 std::vector<std::string> get_all_files_in_directory_posix(const std::string& path) { std::vector<std::string> files; DIR *dir; struct dirent *ent; if ((dir = opendir(path.c_str())) != NULL) { while ((ent = readdir(dir)) != NULL) { // 跳过 "." 和 ".." if (strcmp(ent->d_name, ".") == 0 || strcmp(ent->d_name, "..") == 0) { continue; } // 检查文件类型:在Linux下,d_type可能不总是被支持(比如某些文件系统),所以如果不支持,我们需要用lstat // 这里我们假设d_type可用 if (ent->d_type == DT_REG) { // 普通文件 // 构造完整路径 std::string full_path = path + "/" + ent->d_name; files.push_back(full_path); } } closedir(dir); } else { perror("无法打开目录"); } return files; } #endif /* 说明: 1. 在方法一中,我们使用了C++17标准库,这是跨平台的,代码简洁,推荐使用。 2. 方法二只适用于支持POSIX的系统(如Linux、macOS),在Windows下需要额外处理(比如使用MinGW提供的dirent.h,或者使用Windows API)。 如果用户不能使用C++17,可以考虑以下方案: - 使用Boost.Filesystem(与C++17的filesystem类似) - 使用平台特定的API(Windows使用FindFirstFile/FindNextFile,Linux使用opendir/readdir) 但为了简化,我们主要展示C++17的方法。 示例主函数: */ int main() { std::string path = "/path/to/directory"; // 替换为实际路径 // 使用C++17方法 std::vector<std::string> files = get_all_files_in_directory(path); // 或者,如果是非Windows且没有C++17,可以使用: // #ifndef _WIN32 // std::vector<std::string> files = get_all_files_in_directory_posix(path); // #endif // 输出所有文件 for (const auto& file : files) { std::cout << file << std::endl; } return 0; } /* 注意:在Windows上,路径分隔符可以是'\\'或'/',我们使用string()会自动转换为平台格式。 相关问题: 1. 如何递归获取子目录下的所有文件? 2. 如何按文件扩展名过滤文件? 3. 如何获取文件的修改时间、大小等属性? 4. 在C++17之前,如何跨平台遍历目录? */</think>在 C++获取指定目录下所有文件名,可以使用以下两种主流方法(推荐使用 C++17 标准方法): ### 方法 1:使用 C++17 标准库(跨平台推荐) ```cpp #include <iostream> #include <vector> #include <filesystem> // 获取目录下所有文件名(完整路径) std::vector<std::string> get_all_filenames(const std::string& directory_path) { std::vector<std::string> filenames; // 遍历目录 for (const auto& entry : std::filesystem::directory_iterator(directory_path)) { if (entry.is_regular_file()) { // 只处理普通文件 filenames.push_back(entry.path().string()); } } return filenames; } int main() { std::string path = "/your/target/directory"; // 替换为实际路径 // 获取所有文件名 auto files = get_all_filenames(path); // 打印结果 for (const auto& file : files) { std::cout << file << std::endl; } return 0; } ``` ### 方法 2:使用 POSIX API(Linux/Unix 系统) ```cpp #include <iostream> #include <vector> #include <string> #include <dirent.h> #include <sys/types.h> std::vector<std::string> get_all_filenames(const std::string& path) { std::vector<std::string> files; DIR* dir = opendir(path.c_str()); if (!dir) { perror("目录打开失败"); return files; } struct dirent* entry; while ((entry = readdir(dir)) != nullptr) { // 跳过 "." 和 ".." 目录 if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) continue; // 检查是否为普通文件 (DT_REG) if (entry->d_type == DT_REG) { files.push_back(path + "/" + entry->d_name); } } closedir(dir); return files; } // main 函数同上 ``` ### 关键说明: 1. **C++17 方法优势**: - 跨平台支持(Windows/Linux/macOS) - 代码简洁易读 - 自动处理路径分隔符(`/` 或 `\`) - 编译选项:`-std=c++17`(g++/clang)或 `/std:c++17`(MSVC) 2. **文件类型过滤**: - `entry.is_regular_file()` 确保只获取普通文件(排除目录) - 若需包含目录:移除该判断条件 3. **特殊文件处理**: - 自动跳过 `.`(当前目录)和 `..`(上级目录) - 跳过隐藏文件(如 `.gitignore`):需额外添加文件名检查 4. **路径格式**: - 完整路径:`entry.path().string()` - 仅文件名:`entry.path().filename().string()` ### 文件类型扩展(POSIX) | `d_type` 值 | 说明 | |-------------|-------------------| | `DT_REG` | 普通文件 | | `DT_DIR` | 目录文件 | | `DT_LNK` | 符号链接 | | `DT_FIFO` | 命名管道 | | `DT_SOCK` | Unix 域套接字 | | `DT_CHR` | 字符设备文件 | | `DT_BLK` | 块设备文件 | | `DT_UNKNOWN`| 未知类型 | ### 编译注意事项 ```bash # C++17 方法编译命令 g++ -std=c++17 -o filelist filelist.cpp # POSIX 方法编译命令 g++ -o filelist filelist.cpp ``` > **注意**:C++17 方法需要编译器支持 C++17 标准(GCC 7+,Clang 5+,MSVC 2017 15.7+)[^1][^3]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值