C++跨平台实现文件保存至EXE所在目录的技术问询
CLI应用跨平台固定路径存储文件解决方案
核心问题:为什么argv[0]不好用
- 当通过系统PATH环境变量调用程序时,
argv[0]只会返回程序文件名(比如CLI_App.exe),拿不到完整路径 - 部分调用场景下还会返回异常值(比如你碰到的
true),完全没法用来定位程序所在目录
跨平台实现步骤
1. 用系统API获取程序完整路径
不同平台需要调用各自的系统接口来获取可执行文件的绝对路径:
Windows平台
调用GetModuleFileNameW接口:
#include <windows.h> #include <string> std::wstring get_exe_dir() { wchar_t path[MAX_PATH]; GetModuleFileNameW(NULL, path, MAX_PATH); // 截取目录部分(去掉文件名) std::wstring full_path(path); size_t last_slash = full_path.find_last_of(L"\\/"); return full_path.substr(0, last_slash + 1); }
Linux/macOS平台
Linux用readlink读取/proc/self/exe,macOS用_NSGetExecutablePath做 fallback:
#include <string> #include <unistd.h> #include <limits.h> #include <mach-o/dyld.h> // macOS专属头文件 std::string get_exe_dir() { char path[PATH_MAX]; // 先尝试Linux方式 ssize_t len = readlink("/proc/self/exe", path, PATH_MAX - 1); if (len != -1) { path[len] = '\0'; std::string full_path(path); size_t last_slash = full_path.find_last_of("/"); return full_path.substr(0, last_slash + 1); } // 失败则用macOS方式 uint32_t mac_len = PATH_MAX; if (_NSGetExecutablePath(path, &mac_len) == 0) { std::string full_path(path); size_t last_slash = full_path.find_last_of("/"); return full_path.substr(0, last_slash + 1); } return ""; }
2. 拼接目标文件路径
拿到程序所在目录后,直接拼接文件名即可:
// Windows示例 std::wstring exe_dir = get_exe_dir(); std::wstring target_file = exe_dir + L"example.txt"; // Linux/macOS示例 std::string exe_dir = get_exe_dir(); std::string target_file = exe_dir + "example.txt";
这样不管你在哪个目录下调用程序,文件都会被精准保存到CLI_App.exe所在的目录,不会出现误在当前目录新建同名文件的情况。
3. 跨平台统一封装(可选)
用预编译指令把两个平台的代码封装成一个统一函数,方便跨平台编译:
#include <string> #ifdef _WIN32 #include <windows.h> std::wstring get_exe_directory() { wchar_t path[MAX_PATH]; GetModuleFileNameW(NULL, path, MAX_PATH); std::wstring full_path(path); size_t last_sep = full_path.find_last_of(L"\\/"); return full_path.substr(0, last_sep + 1); } #else #include <unistd.h> #include <limits.h> #include <mach-o/dyld.h> std::string get_exe_directory() { char path[PATH_MAX]; ssize_t len = readlink("/proc/self/exe", path, PATH_MAX - 1); if (len != -1) { path[len] = '\0'; std::string full_path(path); size_t last_sep = full_path.find_last_of("/"); return full_path.substr(0, last_sep + 1); } uint32_t mac_len = PATH_MAX; if (_NSGetExecutablePath(path, &mac_len) == 0) { std::string full_path(path); size_t last_sep = full_path.find_last_of("/"); return full_path.substr(0, last_sep + 1); } return ""; } #endif
验证方法
- 在不同目录下调用程序,比如
C:\Users\Me> CLI_App.exe或/home/user> CLI_App - 检查
example.txt是否出现在程序所在的目录,而非你调用时的当前目录
内容的提问来源于stack exchange,提问作者1cubealot
相关产品推荐
相关产品推荐

