Rust中使用BufWriter实现全局静态变量遇写入无效问题
问题根源
BufWriter 是带缓冲的写入器,你写入的字节会先存在内存缓冲区里,不会立刻写到磁盘。只有满足三个条件之一才会刷盘:
- 缓冲区被写满
- 手动调用
flush()方法 - BufWriter 被销毁(也就是生命周期结束)
你的代码里,全局的 BufWriter 一直处于存活状态,而且只写了4个字节,远没填满默认缓冲区,也没手动触发刷盘,所以数据一直留在内存里,文件自然看不到内容。
解决办法
有两种简单的处理方式:
方法一:写完就手动刷盘
每次调用 write_all 之后,调用 flush() 强制把缓冲区数据写入磁盘。最好把锁的获取合并成一次,减少锁竞争:
let mut writer = WRITER.lock().unwrap(); writer.write_all(&vec![1, 2, 3, 4]).unwrap(); writer.flush().unwrap();
方法二:封装后自动刷盘
如果不想每次都手动调用flush,可以封装一个结构体,利用锁的Guard销毁时机自动触发刷盘:
use lazy_static::lazy_static; use std::fs::File; use std::io::{BufWriter, Write}; use std::sync::{Mutex, MutexGuard}; struct FlushingBufWriter(Mutex<BufWriter<File>>); impl FlushingBufWriter { fn lock(&self) -> impl Drop + Write { let guard = self.0.lock().unwrap(); // 定义辅助结构体,在drop时自动执行flush struct FlushGuard<'a>(MutexGuard<'a, BufWriter<File>>); impl<'a> Drop for FlushGuard<'a> { fn drop(&mut self) { // 可根据需求处理flush错误,这里暂时忽略 let _ = self.0.flush(); } } // 实现Write trait,让FlushGuard可以直接用于写入操作 impl<'a> Write for FlushGuard<'a> { fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> { self.0.write(buf) } fn flush(&mut self) -> std::io::Result<()> { self.0.flush() } } FlushGuard(guard) } } lazy_static! { static ref WRITER: FlushingBufWriter = { let file = File::create("test.bin").unwrap(); FlushingBufWriter(Mutex::new(BufWriter::new(file))) }; } // 使用时直接写入即可,无需手动调用flush WRITER.lock().write_all(&vec![1, 2, 3, 4]).unwrap();
这样每次锁释放的时候,都会自动尝试把缓冲区的数据刷到磁盘里,不用再手动操作。
内容的提问来源于stack exchange,提问作者Alexey Mirano
相关产品推荐
相关产品推荐

