windows路径中绝对禁止的字符是:、*、?、"、、|,共7个,任何位置出现均导致error_invalid_name;/和\仅作分隔符,文件名末尾的/也非法。

Windows下哪些字符绝对不能出现在路径里
Windows对路径字符的限制比Unix系严格得多,:、*、?、"、、<code>>、| 这7个字符在任何位置(文件名、目录名、完整路径)都非法,连CreateFileA都会直接返回ERROR_INVALID_NAME。注意:/ 和 \ 在路径中是分隔符,单独出现不报错,但出现在文件名末尾(如 foo/)会被视为无效名称。
用std::find_first_of快速检测非法字符
别手写循环——C++标准库足够应付这个场景。把所有Windows非法字符放进一个字符串字面量,用std::find_first_of一次扫完:
bool has_invalid_win_char(const std::string& path) {
static const char* invalid = ":*?\"|";
return path.find_first_of(invalid) != std::string::npos;
}
注意点:
和 <code>>在C++字符串字面量里要转义为<和>(或直接用'\x3C'等),否则XML/HTML渲染会出错;实际代码中建议用原始字符串或十六进制- 这个函数只检查Windows规则,Linux/macOS下
/和\0才是关键,但/在路径中合法,真正要拦的是嵌入的空字符'\0' - 如果路径来自用户输入,建议先
trim首尾空白——虽然空白本身不非法,但"foo "这种结尾空格在Windows资源管理器里会被自动截掉,导致后续stat失败
跨平台判断时别忽略\0和控制字符
所有操作系统都禁止路径含空字符'\0',因为C风格字符串以它结尾。更隐蔽的是ASCII控制字符(0x01–0x1F),Linux虽不报错,但shell、tar、git等工具常静默截断或损坏它们。实操建议:
- 用
std::any_of(path.begin(), path.end(), [](char c) { return c == '\0' || (c >= 0 && c 一并检查 - 不要只依赖“是否能
open()成功”来判断——某些非法字符(如CON、AUX这类设备名)在Windows上能创建文件但行为异常,必须提前拦截 - 如果路径用于生成URL或JSON,还要额外过滤
%、#、{等特殊符号,但这属于应用层约束,不是OS路径合法性问题
为什么GetFullPathName不能代替字符检查
有人想用Windows API的GetFullPathNameW来“验证路径”,这是陷阱。它只做解析(比如展开..\、补全驱动器号),不校验字符合法性——传入"a:b*c"照样返回成功,但后续CreateFile必然失败。真正该用的API是PathCchValidateString(Windows 10+),但它只检查基本非法字符,不覆盖保留名(NUL、PRN等),所以仍需组合判断。
最稳妥的做法:先用字符检查过一遍,再对basename单独检查是否为Windows保留名,最后才调用系统API。保留名列表硬编码成本高,建议直接查winbase.h里的INVALID_FILE_NAMES宏定义,或者用现成的开源小函数(如Boost.Filesystem的is_valid_filename内部逻辑)。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











