提问人:Adrodoc 提问时间:7/11/2021 最后编辑:Adrodoc 更新时间:3/2/2023 访问量:561
如何在 rust 中阻止,直到文件有更多数据
How do you block in rust until a file has more data
问:
我正在使用 BufRead::read_line 自动读取由另一个应用程序编写的日志文件:
let file = File::open("foo.log")?;
let mut reader = BufReader::new(file);
let mut line = String::new();
loop {
line.clear();
let size = reader.read_line(&mut line)?;
if size != 0 {
// ... process line
} else {
// How do I block until reader is no longer at EOF?
}
}
当我到达文件末尾时,我想等到更多数据可用。
有没有比忙着等待更好的选择?sleep(Duration::from_millis(50));
我已经研究了通知 crate 以等待写入事件,但看起来在 Windows 上,这些事件仅在文件关闭时发生(即使使用原始 API 时),但在我的情况下,应用程序会保持其日志文件打开状态,直到它被关闭。
使用也可以(甚至首选)。async
答:
0赞
Riton Elion
7/11/2021
#1
似乎有一个 libaray 可以满足您的要求:https://crates.io/crates/notify 但我不确定它是否异步。
评论
0赞
Adrodoc
7/12/2021
不幸的是,这似乎不是 Windows 的解决方案。似乎我在您阅读时编辑了我的问题,对不起:)
1赞
ptdecker
3/2/2023
#2
这是我制定的基于池化的方法的草图。您可以将其与文件的只读打开相结合,查找到最后一个已知大小,然后读取任何更改的数据。显然,这只是一种方法的草图。而且,它仍然使用线程睡眠。但是,我没有找到更好的方法来解决同样的问题。我很想知道你是否曾经想出一个解决方案。
use std::{fs, thread, time};
use std::time::SystemTime;
fn main() {
let pool_interval = 1; // seconds
let path = "../path/logs/logfile.log".to_string();
println!("watching {}", path);
let mut last_modified:u64 = 0;
loop {
let attr = fs::metadata(&path).unwrap();
let modified = attr.modified().unwrap().duration_since(SystemTime::UNIX_EPOCH).unwrap().as_secs();
if modified != last_modified {
last_modified = modified;
let filesize = attr.len();
println!("modified: {:?}, new size: {:?}", modified, filesize);
}
thread::sleep(time::Duration::from_secs(pool_interval))
}
}
评论
3赞
Adrodoc
3/3/2023
我们最终使用的解决方案是通知箱和轮询的混合。我们等待写入事件,但有超时。如果超时期间没有发生任何事件,我们仍然会继续读取。我们还使阅读器保持打开状态,以确保在日志文件轮换时不会错过最后一行。幸运的是,日志文件轮换总是会产生创建事件,即使在 Windows 上也是如此。发生这种情况时,我们重新打开路径以获取新文件的句柄。代码可以在这里看到:github.com/vanilla-technologies/minect/blob/...
0赞
ptdecker
3/4/2023
@Adrodoc感谢您跟进我
评论
tail -f
inotify
sleep