file.getcreationtime 不准是因文件系统差异:ntfs 可信,fat32/exfat/网络盘常退为 lastwritetime,linux/macos 无创建时间故也退为 lastwritetime;跨平台应优先用 lastwritetime 并转 touniversaltime,强依赖时需应用层自存时间戳。

File.GetCreationTime 返回的时间不准?先确认时区和文件系统行为
Windows 上 File.GetCreationTime 返回的是 NTFS 卷上记录的创建时间戳,但 FAT32、exFAT 或网络共享(SMB)可能根本不保存该字段,此时 .NET 会退回到最后写入时间(LastWriteTime),甚至返回一个固定假值(如 1970-01-01)。不是 API 有问题,是底层没存。
- 本地 NTFS 文件:可信,但注意 Windows 资源管理器复制/移动时默认重置创建时间(可用
robocopy /COPYALL保留) - FAT32/exFAT/U 盘:
GetCreationTime常等于GetLastWriteTime,别依赖它做业务判断 - OneDrive/Google Drive 同步目录:元数据由客户端模拟,创建时间基本不可信
- 代码里别直接用
File.GetCreationTime(path)就完事,先检查File.Exists(path),否则抛FileNotFoundException
想跨平台稳定读取“首次写入时间”,优先用 LastWriteTime
Linux/macOS 文件系统(ext4、APFS、ZFS)压根不提供标准“创建时间”字段;.NET 6+ 在这些平台上对 File.GetCreationTime 的实现直接回退到 LastWriteTime。如果你要的是“这个文件内容第一次落盘的时间”,LastWriteTime 反而更一致、更可靠。
- 跨平台工具或 CLI 工具中,统一用
File.GetLastWriteTime(path)替代创建时间逻辑 - 若业务强依赖“创建”语义(比如审计日志),必须在应用层自己写入时间戳到文件头或配套 JSON 元数据文件,不能靠 OS
-
LastWriteTime仍受时区影响:返回DateTime默认是Localkind,序列化前建议转成Utc:File.GetLastWriteTime(path).ToUniversalTime()
获取完整文件系统元数据(非仅时间),用 FileInfo 更可控
FileInfo 比静态 File 方法多一层封装,能复用实例、避免重复路径解析,还能提前捕获权限/访问异常。
- 先 new
FileInfo(path),再访问CreationTime、LastAccessTime、Length等属性——所有属性共用一次文件系统调用,比多次调用File.Xxx略快 -
FileInfo构造时不会立即查磁盘,但首次访问任一时间属性时会触发Refresh();如果路径无效或无权限,异常发生在属性访问时,不是构造时 - 注意
Exists属性:它内部也调用Refresh(),所以if (fi.Exists) { ... fi.CreationTime ... }是安全的,不会重复 IO
PowerShell 或命令行对比验证时,注意 Windows 和 .NET 的时间显示差异
PowerShell 的 Get-Item xxx.txt | % CreationTime 显示的是本地时区格式化后的时间,而 C# 中 DateTime.ToString() 默认也走本地格式——但两者底层来源可能不同。比如 PowerShell 在某些 SMB 场景下会把服务器时区当成本地处理,而 .NET 默认信任系统时区设置。
- 调试时统一用
ToString("o")(ISO 8601 格式)输出,例如:fi.CreationTime.ToString("o")→2023-05-12T14:22:03.1234567+08:00 - 对比 PowerShell 结果时,加
-Format Roundtrip:(Get-Item x.txt).CreationTime.ToString("o") - 别信资源管理器“详细信息”视图里的“创建日期”列——它可能被排序/缓存策略干扰,实际查的是缩略图缓存或上次索引结果
事情说清了就结束。真正难的不是怎么调 API,而是搞明白你到底要哪个“创建”:是 NTFS 卷上的原始标记,还是用户心理预期的“第一次保存”,抑或是需要审计合规的“应用层打标”。这三个根本不在一个抽象层上。










