File.SetAttributes 是修改文件只读属性最直接可靠的方式,需先读取当前属性再按位操作,避免覆盖其他属性;FileInfo.Attributes 更适合多次操作;注意权限、路径存在性及跨平台差异。

用 File.SetAttributes 修改文件只读属性最直接
修改单个文件的只读状态,File.SetAttributes 是最常用且可靠的方式。它底层调用 Windows API 或类 Unix 系统的权限接口,不依赖外部命令或 Shell 脚本。
关键点是:必须显式传入完整属性集合,不能只加/减 FileAttributes.ReadOnly —— 否则会覆盖隐藏、系统、存档等其他属性。
- 先读取当前属性:
var attrs = File.GetAttributes(path) - 设为只读:
File.SetAttributes(path, attrs | FileAttributes.ReadOnly) - 取消只读:
File.SetAttributes(path, attrs & ~FileAttributes.ReadOnly) - 路径必须存在,否则抛
FileNotFoundException
用 FileInfo.Attributes 更适合多次操作
如果需要连续读写多个属性(比如同时设置只读 + 隐藏),FileInfo 更方便,避免重复调用 File.GetAttributes。
它的 Attributes 属性是可读写的,但赋值时仍需注意“全量覆盖”逻辑:
var fi = new FileInfo(path); fi.Attributes |= FileAttributes.ReadOnly;fi.Attributes &= ~FileAttributes.ReadOnly;- 若
path不存在,构造FileInfo不报错,但访问Attributes会抛FileNotFoundException
常见错误:权限不足或路径被占用
即使代码语法正确,运行时仍可能失败。典型错误信息包括:
-
UnauthorizedAccessException:当前进程无权修改该文件属性(如文件在系统目录、被其他进程锁定、或用户权限受限) -
IOException:“The process cannot access the file…”:文件正被记事本、VS、资源管理器等打开 - 对网络路径(如
\servershareile.txt)操作时,部分 SMB 共享不支持属性变更,返回NotSupportedException
建议操作前加 try/catch 捕获这些异常,并提示用户检查文件是否关闭、UAC 是否启用、共享配置是否允许属性写入。
跨平台注意事项:Linux/macOS 下只读含义不同
.NET 6+ 在非 Windows 系统上,FileAttributes.ReadOnly 实际映射为文件权限中的 “write bit off”。但 Linux 文件系统没有“只读属性”概念,只有 rwx 权限位。
- 调用
File.SetAttributes(path, FileAttributes.ReadOnly)在 Linux 上等价于执行chmod -w path - 若原始权限是
rw-r--r--,设只读后变成r--r--r--;但不会影响执行位或属主/组关系 - 不推荐在跨平台项目中依赖
ReadOnly做业务逻辑判断,应改用File.GetAccessControl()或stat等更底层方式
真正容易被忽略的是:很多开发者以为设了 ReadOnly 就能阻止所有写入,但实际上只是绕过部分 .NET I/O 方法的默认检查;直接用 FileStream 打开并写入依然可能成功(尤其在 Windows 上)。真要防写,得结合 ACL 或文件锁。


















