C++读取文件系统问题:Boost编译失败及替代方案咨询
解决Windows下32位MinGW环境的目录扫描问题
一、关于MinGW GCC 7的获取
你可以直接下载32位MinGW GCC 7.x版本的预编译包,比如选择MinGW官方镜像或第三方维护的MinGW-w64分支的i686架构包。而且Code::Blocks支持多编译器配置,不用替换原有GCC5,直接新增一套编译器即可:
- 下载32位GCC7压缩包,解压到独立目录(比如
C:\MinGW-GCC7) - 打开Code::Blocks,进入
Settings > Compiler > Global compiler settings - 点击
Copy,命名为MinGW GCC 7 32-bit - 在
Toolchain executables标签页,把编译器路径改成你解压的GCC7的bin目录 - 确认
C compiler、C++ compiler等工具的文件名正确(比如gcc.exe、g++.exe)
配置完成后,就能在项目中切换到支持C++17的编译器,直接用<filesystem>库实现需求,代码会简洁很多。
二、修复你自己实现的_findfirst递归扫描代码
你的当前代码有几个关键问题,导致无法正确识别目录和递归扫描:
- 硬编码了搜索路径:把
_findfirst参数写成了"C:/",而非传入的searchPath,导致无论传什么路径都只扫C盘根目录 - 缺少目录递归逻辑:没有判断当前项是否为目录,无法进入子目录扫描
- 文件路径未正确拼接:
filePath变量未赋值,需要把searchPath和dirFile.name拼接成完整路径 - 扩展名判断逻辑错误:
substr(len-4, len - 1)写法有误,且未考虑文件名长度小于4的情况
修复后的代码示例:
#include <vector> #include <string> #include <io.h> #include <windows.h> #include <iostream> #include <algorithm> using namespace std; struct FileTimes { FILETIME written; FileTimes(const string& path) { WIN32_FILE_ATTRIBUTE_DATA data; if (GetFileAttributesExA(path.c_str(), GetFileExInfoStandard, &data)) { written = data.ftLastWriteTime; } } FILETIME getWritten() { return written; } }; vector<pair<string, FILETIME>> searchDir(const string searchPath, const string searchStr) { cout << "searchDir(" << searchPath << ", " << searchStr << ")" << endl; vector<pair<string, FILETIME>> files; struct _finddata_t dirFile; // 构造带通配符的搜索模式 string searchPattern = searchPath + "/*"; intptr_t hFile = _findfirst(searchPattern.c_str(), &dirFile); if (hFile == -1) { cout << "Search Path not found: " << searchPath << endl; return files; } do { if (!strcmp(dirFile.name, ".") || !strcmp(dirFile.name, "..")) { continue; // 跳过自身和父目录 } if (dirFile.attrib & _A_HIDDEN) { continue; // 跳过隐藏文件 } // 拼接完整文件/目录路径 string fullPath = searchPath + "/" + dirFile.name; // 如果是目录,递归扫描子目录 if (dirFile.attrib & _A_SUBDIR) { auto subFiles = searchDir(fullPath, searchStr); files.insert(files.end(), subFiles.begin(), subFiles.end()); } else { // 判断文件扩展名 size_t dotPos = string(dirFile.name).find_last_of('.'); if (dotPos != string::npos) { string ext = string(dirFile.name).substr(dotPos); // 若需要不区分大小写,可以转成小写后比较 if (ext == searchStr) { FileTimes f(fullPath); files.emplace_back(fullPath, f.getWritten()); } } } } while (_findnext(hFile, &dirFile) == 0); _findclose(hFile); return files; } // 测试用例 int main() { auto result = searchDir("C:/test", ".txt"); for (auto& file : result) { cout << "File: " << file.first << endl; } return 0; }
三、修复Boost库的编译问题
你遇到的gcc未识别问题,是因为Windows命令行中路径含空格时需要加引号,且path命令写法有误。正确步骤如下:
- 以管理员身份打开命令提示符,进入Boost目录:
cd "C:\Program Files\Boost\boost_1_67_0" - 添加MinGW的bin目录到环境变量(注意路径加引号):
set PATH="C:\Program Files (x86)\CodeBlocks\MinGW\bin";%PATH% - 执行bootstrap脚本:
bootstrap.bat mingw - 编译32位Boost库(匹配你的32位环境):
b2 toolset=gcc address-model=32 --build-type=complete stage
编译完成后,在Code::Blocks中配置Boost:
- 进入
Settings > Compiler > Search directories,添加Boost的include目录(C:\Program Files\Boost\boost_1_67_0) - 进入
Linker settings,添加Boost的stage/lib目录下的libboost_filesystem-mgw53-mt-1_67.a等相关库文件
四、最终建议
因为你的程序只在两台相同机器运行,不需要考虑可移植性,最省事的方案是直接升级到MinGW GCC7,然后用C++17的<filesystem>库实现,代码简洁且可靠:
#include <filesystem> #include <vector> #include <string> #include <windows.h> namespace fs = std::filesystem; std::vector<std::pair<std::string, FILETIME>> searchDir(const fs::path& searchPath, const std::string& ext) { std::vector<std::pair<std::string, FILETIME>> files; for (const auto& entry : fs::recursive_directory_iterator(searchPath)) { if (entry.is_regular_file() && entry.path().extension() == ext) { WIN32_FILE_ATTRIBUTE_DATA data; if (GetFileAttributesExA(entry.path().string().c_str(), GetFileExInfoStandard, &data)) { files.emplace_back(entry.path().string(), data.ftLastWriteTime); } } } return files; }
内容的提问来源于stack exchange,提问作者Joseph C. Caswell
相关产品推荐
相关产品推荐

