rust - 自动读取文件内容

标签 rust

在 Linux 上,如果有一个长时间运行的进程每秒将时间戳写入文本文件,我如何自动从该文件读取时间戳?

这是我当前的实现:

fn read_timestamp() -> Result<String, &'static str> {
    let path = "/timestamp.txt";
    let metadata_result = fs::metadata(path);
    match metadata_result {
        Ok(_) => {
            let lock_result = FileLock::lock(path, true, true);
            match lock_result {
                Ok(mut lock) => {
                    let mut content = String::new();
                    let read_result = lock.file.read_to_string(&mut content);
                    if read_result.is_ok() {
                        Ok(content)
                    } else {
                        Err("Cannot read file")
                    }
                },
                Err(_) => Err("Cannot acquire lock")
            }
        },
        Err(_) => Err("File not found")
    }
}

它看起来很笨重,我希望得到一些反馈。

最佳答案

我看到的一个大问题是锁定是活泼的,这实际上不会导致问题,但会导致不必要和无益的系统调用流量:从技术上讲,可以在对元数据的调用之间删除文件> 和 FileLock::lock

所以我可能会直接执行 FileLock::lock 调用,然后检查其错误内容以进行错误报告,失败时返回 io::Error所以应该告诉您,它具体出错是因为该文件不存在。

我觉得有点奇怪的另一件事是你对 match 的依赖,特别是考虑到你很少使用错误。

我倾向于使用更高级别的组合器,或用于一元或二进制代码路径的 if let (特别是在忽略回退的有效负载时)。创建局部变量只是为了立即将其移动到匹配项也不是很习惯,您通常不会为局部变量操心。 YMMV 不过,它本身当然没有错误,它只是比我认为必要或合理的噪音更大。

这也可能受益于定制的错误类型,避免显式错误和匹配。无论如何,这是一个没有自定义错误类型的可能版本:

fn read_timestamp2() -> Result<String, &'static str> {
    let path = "/timestamp.txt";
    match FileLock::lock(path, true, true) {
        Ok(mut lock) => {
            let mut content = String::new();
            lock.file.read_to_string(&mut content)
                .map(|_| content)
                .map_err(|_| "Cannot read file")
        },
        Err(e) if e.kind() == NotFound => Err("File not found"),
        Err(_) => Err("Cannot acquire lock")
    }
}

您可以进一步了解码合器:

fn read_timestamp() -> Result<String, &'static str> {
    let path = "/timestamp.txt";
    FileLock::lock(path, true, true)
        .and_then(|mut lock| {
            let mut content = String::new();
            lock.file.read_to_string(&mut content)
                .map(|_| content)
        })
        .map_err(|e| match e.kind() {
            NotFound => Err("File not found"),
            Interrupted | PermissionDenied | WouldBlock
                => Err("Cannot acquire lock"),
            _ => Err("Cannot read file")
        })
    }
}

但请注意,此代码在其错误报告中并不真正正确:ErrorKind相当不精确,所以实际上您需要调用 raw_os_error并交叉引用手册页以了解哪些内容来自何处。

说实话,第二个版本有点古怪。

关于rust - 自动读取文件内容,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66594279/

相关文章:

rust - 如何使用货箱列出项目的源文件?

null - 我们应该使用 Option 还是 ptr::null 来表示 Rust 中的空指针?

rust - 本地拥有的引用资料被认为是借来的

c - Rust 的函数参数语法相对于 C 的目的是什么?

rust - 有什么理由在 panic 之后加上分号吗?

rust - 在 Rust 中实现通用的可递增特征

rust - 如何在二进制项目中使用 src 文件夹外部的模块,例如用于集成测试或基准测试?

pointers - 使用rust "Borrowed pointers"语法

rust - 为什么 Mutex 包含一个 Box?

types - 克隆特性 BufRead 的行时类型不匹配