std::Filesystem::rename是唯一推荐方案,因其跨平台、自动处理路径分隔符与utf-8/utf-16编码转换、提供明确异常类型和错误码,而c风格rename()在windows下对中文路径、长路径及跨卷操作几乎必失败。

直接用 std::filesystem::rename,别碰 C 风格的 rename() —— 后者在 Windows 上对中文路径、长路径、跨卷操作几乎必挂。
为什么 std::filesystem::rename 是唯一推荐方案
c++17 引入的 std::filesystem 是跨平台且语义明确的替代品。它自动处理路径分隔符(/ vs )、编码(Windows 下 UTF-8 输入会正确转为 UTF-16 调用系统 API)、权限检查和错误分类。而 C 标准库的 rename() 在 Windows 上底层调用的是 _wrename() 的窄字符封装,遇到非 ASCII 字符基本静默失败。
- Windows 下
rename("旧文件.txt", "新文件.txt")对中文名大概率返回 -1 且errno为 2(ENOENT),实际文件存在 -
std::filesystem::rename抛出的异常类型明确:std::filesystem::filesystem_error,可捕获.code().value()查具体系统错误码 - 支持相对路径、
std::filesystem::path对象、甚至符号链接目标重命名(取决于 OS 策略)
std::filesystem::rename 的典型用法与参数陷阱
核心就一行,但路径构造和异常处理不能省:
#include <filesystem> namespace fs = std::filesystem; try { fs::rename("old_name.txt", "new_name.txt"); // ✅ 推荐:字符串字面量(UTF-8 编码) // 或 fs::rename(fs::path("src") / "log.txt", fs::path("dst") / "archive.log"); } catch (const fs::filesystem_error& e) { // e.code().value() == 18 通常是 EXDEV(跨设备/分区),需用复制+删除模拟 // e.what() 包含可读提示,如 "No such file or directory" }
- 源路径和目标路径都必须是完整路径或同级相对路径;若目标已存在,行为依平台而定(POSIX 覆盖,Windows 默认失败)
- 目标路径不能是目录(除非源也是目录且为空);若要覆盖已有文件,得先
fs::remove("new_name.txt") - 跨卷(如 C: → D:)在 Windows/linux 均报
EXDEV,此时必须手动fs::copy_file+fs::remove
Windows 下中文路径失效?检查编译器和运行时设置
即使用了 std::filesystem,VS2019/2022 默认仍可能因窄字符环境导致中文路径被截断:
立即学习“C++免费学习笔记(深入)”;
- 确保项目属性 → “常规” → “字符集” 设为“使用 Unicode 字符集”(不是“未设置”)
- MSVC 编译时加
/utf-8参数,强制源文件和字符串字面量按 UTF-8 解析 - 避免用
std::String拼接路径;优先用fs::path构造:fs::path(L"中文目录") / L"文件.txt"(宽字符字面量更稳妥) - MinGW-w64 用户注意:需链接
-lstdc++fs,否则链接失败
真正麻烦的从来不是 rename 这个动作本身,而是路径合法性判断、目标是否存在、是否跨设备、以及错误后该重试还是降级处理——这些逻辑没包进标准库,得自己补全。