C#中Windows非法文件名字符包括'', '|', '*', '?', ':', '"', '', '/'及ASCII控制字符( –),不包含路径分隔符''和'/';应使用Path.GetInvalidFileNameChars()获取并清理,同时需校验DOS设备名及末尾空格/点号。

哪些字符在C#中会被视为非法文件名字符
Windows系统对文件名有明确限制,Path.GetInvalidFileNameChars() 返回的字符列表就是实际禁止出现在文件名(不含路径分隔符)中的字符。注意:它不包含 '\' 和 '/' —— 这两个是路径分隔符,由 Path.GetInvalidPathChars() 单独返回。常见非法字符包括 '、'>'、'|'、'*'、'?'、':'、'"'、''、'/',还有 ASCII 控制字符( –)。
用 Path.GetInvalidFileNameChars() 做基础清理
直接遍历替换最稳妥,尤其适合保留原始语义(比如把 ' 替成 '(','>' 替成 ')')。不要用正则预编译匹配所有非法字符,因为 GetInvalidFileNameChars() 返回的是 char[],部分字符在正则里需转义或有边界问题。
- 先调用
Path.GetInvalidFileNameChars()获取当前运行环境(.NET 版本 + OS)认可的非法字符集,不同 .NET 版本略有差异 - 对文件名部分(不是整个路径)做替换,避免误删路径分隔符
- 推荐用
string.Concat(chars.Where(c => !invalidChars.Contains(c)))或手动StringBuilder遍历,性能比Replace链式调用更可控 - 空格、点号(
'.')、下划线('_')是合法的,无需处理;但首尾点号或空格在某些 API(如File.Create)中可能引发意外行为,建议额外 trim
替换策略选“安全字符”还是“删除”
替换为 '_' 是最通用做法,比删除更利于追溯原始意图;但若业务要求严格保持长度一致(如日志归档),可考虑删除非法字符。注意:连续多个非法字符替成一个 '_' 能避免生成 ___.txt 这类难读文件名。
- 避免替换成
'-':在某些命令行上下文里可能被误解析为参数开关 - 避免替换成
' '(空格):容易在脚本或旧工具中引发截断 - 如果目标是 URL 友好型文件名,还需额外处理 Unicode 字符(比如用
Uri.EscapeDataString或自定义拼音映射),GetInvalidFileNameChars()不覆盖这部分 - .NET 5+ 中
Path.GetInvalidPathChars()在 Linux/macOS 下返回空数组,但跨平台应用仍应统一用 Windows 规则做清洗,否则部署到 Windows 时会失败
别忘了验证清理后的文件名是否仍合法
清理完别直接 File.WriteAllText —— 有些名字虽无非法字符,但仍不可用,比如 "CON"、"PRN"、"AUX" 等 DOS 设备名(不区分大小写),或末尾带 '.' 或 ' ' 的名字。这些不会被 GetInvalidFileNameChars() 捕获。
- 检查是否为保留设备名:
string.Equals(name, "CON", StringComparison.OrdinalIgnoreCase)等逐个比对 - 调用
name.TrimEnd('.', ' ').Length == 0排除全空或只剩分隔符的情况 - 最终建议用
try { File.Create(path).Close(); } catch (IOException) { /* 处理 */ }做兜底验证,因为操作系统级限制(如路径总长 > 260)无法靠字符清洗提前发现
实际中最容易被忽略的是设备名校验和跨平台路径语义差异——字符清理只是第一关,后续创建前的轻量级试探性 IO 才真正可靠。










