C#中File.GetCreationTime()和FileInfo.CreationTime在Windows NTFS下可靠,但在FAT32、网络共享、WSL或Docker中可能返回1601-01-01(FILETIME零值),因文件系统不支持或时间戳未保留;跨平台应降级使用LastWriteTime。

直接说结论:C# 中用 File.GetCreationTime() 或 FileInfo.CreationTime 获取文件创建时间,但 Windows 和 NTFS 下才真正可靠;在 FAT32、网络共享、某些 Docker 容器或 WSL 环境中,这个值可能被重置、伪造,甚至返回默认时间(如 1601-01-01)。
为什么 File.GetCreationTime() 有时返回 1601-01-01?
这是 Windows FILETIME 的零值(表示公元 1601 年 1 月 1 日),意味着系统根本没记录该文件的创建时间。常见原因:
- 文件来自 FAT32 分区(不支持创建时间元数据)
- 通过 ZIP 解压、FTP 上传、rsync 同步等操作,原始时间戳未被保留
- 在 WSL2 中访问 Windows 文件系统时,部分发行版默认禁用创建时间透传(需开启
wsl.conf中的metadata = true) - 某些备份工具或云盘客户端会主动清空或重写
CreationTime
验证方法:dir /tc 在命令行查看“创建时间”列是否为空或异常;若为空,C# 读到的就是 1601 时间。
FileInfo.CreationTime 和 File.GetCreationTime() 选哪个?
二者底层调用一致,差异在于使用方式和缓存行为:
-
File.GetCreationTime(string path)是静态方法,每次调用都触发一次系统 API 查询,适合单次读取 -
FileInfo实例会缓存属性(包括CreationTime),适合多次访问同一文件的多个属性(如大小、修改时间、创建时间) - 如果路径可能不存在,
File.GetCreationTime()会抛FileNotFoundException;而FileInfo构造函数不会立即报错,但首次访问CreationTime时仍会抛出
示例对比:
// 推荐:只需创建时间,且路径确定存在 DateTime ct1 = File.GetCreationTime(@"C:\data\report.txt"); <p>// 推荐:还需获取 Length、LastWriteTime 等,避免重复 IO FileInfo fi = new FileInfo(@"C:\data\report.txt"); DateTime ct2 = fi.CreationTime; long size = fi.Length; DateTime mtime = fi.LastWriteTime;
跨平台兼容性下如何稳妥获取“最早可得的时间”?
.NET 6+ 支持跨平台,但 Unix-like 系统(Linux/macOS)根本不提供“创建时间”(birth time),只有 ext4/btrfs 等少数文件系统支持,且 .NET 不暴露该字段。此时应降级为 LastWriteTime 或 LastAccessTime,并明确注释逻辑:
- Windows + NTFS:优先用
CreationTime - 其他平台或
CreationTime == DateTime.MinValue:fallback 到LastWriteTime - 避免假设
CreationTime < LastWriteTime—— 用户可能手动改过创建时间(例如用touch -d或 PowerShellSet-ItemProperty)
简明 fallback 写法:
FileInfo fi = new FileInfo(path);
DateTime effectiveTime = fi.CreationTime == DateTime.MinValue
? fi.LastWriteTime
: fi.CreationTime;
真正容易被忽略的点是:不要把 CreationTime 当作“文件内容生成时间”——它只是文件系统记录的 inode 创建时刻,和业务意义上的“文档撰写完成时间”毫无关系。如果你需要后者,得靠文件内容解析(如 Office 文档的 DocumentProperties)、版本控制系统(git commit time)或应用层埋点。


















