Daxia Blog
Uncategorized | Rust | WebUI | FHIR | Javascript | KB

Rust中如何跨操作系统获取文件的创建时间属性

Rust标准库提供的std::fs::Metadata用于获取文件的属性元数据。

以下是示例代码:

use std::fs;

fn main() -> std::io::Result<()> {
    let metadata = fs::metadata("foo.txt")?;

    if let Ok(time) = metadata.created() {
        println!("{time:?}");
    } else {
        println!("Not supported on this platform or filesystem");
    }
    Ok(())
}

问题

我在编写跨操作系统服务程序时,发现在我的Mac开发机器上这段代码运行没有问题,但是到了生产环境中的Linux服务器(Ubuntu 20.04.3 LTS - GNU/Linux 5.4.0-100-generic x86_64)上就报错,提示方法不被支持的。

通过查阅官方资料发现:

The returned value corresponds to the btime field of statx on Linux kernel starting from to 4.11, the birthtime field of stat on other Unix platforms, and the ftCreationTime field on Windows platforms.

以及

This field might not be available on all platforms, and will return an Err on platforms or filesystems where it is not available.

资料表明,该调用方法不是所有平台都适用的。

解决方法

经过多次查找资料后发现,标准库还是提供了解决方案的。

在标准库中搜索Metadata时,发现有很多针对不同操作系统的trait

  • trait std::os::linux::fs::MetadataExt: 特定于Linux操作系统的
  • trait std::os::unix::fs::MetadataExt: 特定于Unix操作系统的
  • trait std::os::wasi::fs::MetadataExt: 特定于WASI操作系统的
  • trait std::os::windows::fs::MetadataExt: 特定于Windows操作系统的

std::fs::Metadata对这些Trait进行了实现。

最后在程序中,需要针对不同的操作系统编写如下代码:

use std::fs;
use std::path::Path;

fn main() -> std::io::Result<()> {
    let time = get_file_created("foo.txt");
    println!("{time:?}");

    Ok(())
}

#[cfg(target_os = "unix")]
pub fn get_file_created<P: AsRef<Path>>(path: P) -> i64 {
    let meta = fs::metadata(path).unwrap();
    use std::os::unix::fs::MetadataExt;
    meta.ctime()
}

#[cfg(target_os = "linux")]
pub fn get_file_created<P: AsRef<Path>>(path: P) -> i64 {
    let meta = fs::metadata(path).unwrap();
    use std::os::linux::fs::MetadataExt;
    meta.st_ctime()
}

最后,在我的MacOS开发机器上和Linux生产服务器上都测试通过。

About Daxia
我是一名独立开发者,国家工信部认证高级系统架构设计师,在健康信息化领域与许多组织合作。具备大型卫生信息化平台产品架构、设计和开发的能力,从事软件研发、服务咨询、解决方案、行业标准编著相关工作。
我对健康信息化非常感兴趣,尤其是与HL7和FHIR标准的健康互操作性。我是HL7中国委员会成员,从事FHIR培训讲师和FHIR测评现场指导。
我还是FHIR Chi的作者,这是一款用于FHIR测评的工具。