File.GetAttributes(path) & FileAttributes.Compressed == FileAttributes.Compressed 可判断NTFS压缩状态,仅适用于NTFS卷;设置时需先读取再修改标志位,递归压缩需手动遍历或调用compact.exe。

用 File.GetAttributes 检查文件是否启用NTFS压缩
NTFS压缩状态是 Windows 文件系统属性之一,对应 FileAttributes.Compressed 标志。直接读取文件属性即可判断,无需额外 API 调用:
-
File.GetAttributes(path)返回FileAttributes枚举值,按位与FileAttributes.Compressed即可判断 - 注意:该方法对文件和文件夹都有效,但仅当路径实际位于 NTFS 卷上时结果才有意义(FAT32/exFAT 不支持)
- 若路径不存在或无访问权限,会抛出
FileNotFoundException或UnauthorizedAccessException
var attr = File.GetAttributes(@"C: estcompressed.txt"); bool isCompressed = (attr & FileAttributes.Compressed) == FileAttributes.Compressed;
用 File.SetAttributes 启用或禁用NTFS压缩
设置压缩状态本质是修改 FileAttributes.Compressed 标志,但必须配合其他必要属性(如 Normal、Directory 等),否则可能意外清除只读、隐藏等原有属性:
- 正确做法:先读取当前属性,再按需添加或移除
Compressed标志,最后写回 - 对文件夹设置压缩时,仅影响该文件夹自身属性;子项是否压缩取决于其各自属性,不会自动继承
- 调用后系统会异步执行压缩/解压,返回不表示操作已完成;大文件可能延迟数秒才真正完成压缩
var attr = File.GetAttributes(path);
if (enableCompression)
attr |= FileAttributes.Compressed;
else
attr &= ~FileAttributes.Compressed;
File.SetAttributes(path, attr);
递归处理文件夹及其内容的压缩状态
Windows 资源管理器右键“属性→高级”中勾选“将更改应用于此文件夹、子文件夹和文件”,本质是调用 Win32 API SetFileCompression(非托管)或通过 compact.exe 工具。C# 标准库不提供原生递归压缩能力:
- 手动递归需遍历所有子项(
Directory.GetFiles+Directory.GetDirectories),逐个调用File.SetAttributes - 但注意:对文件夹本身设置
Compressed属性,并不会让新创建的文件自动压缩;它只是个提示,实际行为由系统策略和文件操作方式决定 - 更可靠的方式是调用系统命令:
Process.Start("compact", "/c /s:"C:\myfolder"")(启用)或/u(取消)
常见误判场景和权限限制
即使代码逻辑正确,仍可能得到错误结果或抛异常:
- 运行程序的账户必须对目标路径具有“绕过遍历检查”(BYO)权限,否则访问深层嵌套路径时可能被拒绝——这与普通读写权限无关
- 某些系统保护路径(如
C:Windows下)即使管理员运行也可能被阻止设置压缩 - 符号链接、挂载点、重解析点(reparse points)返回的属性反映的是链接本身,而非目标文件的实际压缩状态
- 使用
\?前缀长路径时,确保传入File.GetAttributes的路径格式一致,否则可能因路径规范化失败导致ArgumentException
NTFS 压缩是透明的,但它的生效边界比表面看起来更模糊:属性可读可写,但实际压缩行为受驱动层控制、缓存影响、甚至磁盘配额策略干扰。别依赖单次 GetAttributes 结果做关键决策。









