Rust使用serde_json读写文件时遭遇EOF解析错误求助
问题原因
你遇到的EOF while parsing a value错误,核心原因是文件读写指针的位置问题:
- 调用
serde_json::to_writer完成写入后,文件的读写指针停留在文件末尾位置 - 紧接着用同一个文件句柄创建
BufReader读取时,会从末尾开始读,自然没有任何数据,触发EOF错误
你代码里用到的truncate(true)参数,作用是打开文件时清空原有内容,和本次错误无关——它只是确保写入前文件是空的。
解决方法
这里提供两种可行的修复方案:
方案一:将文件指针移回开头
在写入完成后,通过seek方法把文件指针重置到文件起始位置,再进行读取。需要修改两处:
- 将文件句柄声明为可变(
mut),因为seek需要可变引用 - 调用
seek重置指针位置
修改后的代码:
use std::collections::HashMap; use std::error::Error; use std::fs::OpenOptions; use std::io::{BufReader, Seek, SeekFrom}; // 新增Seek和SeekFrom的导入 fn main() -> Result<(), Box<dyn Error>> { let mut map: HashMap<String, String> = HashMap::new(); map.insert("foo".to_string(), "bar".to_string()); map.insert("hello".to_string(), "you".to_string()); map.insert("to".to_string(), "you".to_string()); println!("{:?}", map); // 这里添加mut,让file可变 let mut file = OpenOptions::new() .read(true) .write(true) .truncate(true) .open("foo_serde.json")?; serde_json::to_writer(&file, &map)?; // 将指针移回文件开头 file.seek(SeekFrom::Start(0))?; let reader = BufReader::new(file); let output: HashMap<String, String> = serde_json::from_reader(reader)?; println!("{:?}", output); Ok(()) }
方案二:分开打开文件(更直观)
这种方式完全避免指针位置的问题:先打开文件写入并关闭,再重新打开文件读取。代码逻辑更清晰,适合简单场景:
use std::collections::HashMap; use std::error::Error; use std::fs::OpenOptions; use std::io::BufReader; fn main() -> Result<(), Box<dyn Error>> { let mut map: HashMap<String, String> = HashMap::new(); map.insert("foo".to_string(), "bar".to_string()); map.insert("hello".to_string(), "you".to_string()); map.insert("to".to_string(), "you".to_string()); println!("{:?}", map); // 单独打开文件写入,写完后自动关闭 let file = OpenOptions::new() .write(true) .truncate(true) .create(true) // 确保文件不存在时创建 .open("foo_serde.json")?; serde_json::to_writer(file, &map)?; // 重新打开文件读取 let file = OpenOptions::new() .read(true) .open("foo_serde.json")?; let reader = BufReader::new(file); let output: HashMap<String, String> = serde_json::from_reader(reader)?; println!("{:?}", output); Ok(()) }
额外说明
- 方案一更适合需要保持文件句柄打开的复杂场景,方案二更适合简单的读写分离场景
- 如果你需要确保写入的数据完全刷到磁盘(避免缓存问题),可以在写入后调用
file.sync_all()?,不过在这个示例中不是必须的
内容的提问来源于stack exchange,提问作者jfboisvieux
相关产品推荐
相关产品推荐

