You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Rust使用serde_json读写文件时遭遇EOF解析错误求助

问题原因

你遇到的EOF while parsing a value错误,核心原因是文件读写指针的位置问题:

  • 调用serde_json::to_writer完成写入后,文件的读写指针停留在文件末尾位置
  • 紧接着用同一个文件句柄创建BufReader读取时,会从末尾开始读,自然没有任何数据,触发EOF错误

你代码里用到的truncate(true)参数,作用是打开文件时清空原有内容,和本次错误无关——它只是确保写入前文件是空的。

解决方法

这里提供两种可行的修复方案:

方案一:将文件指针移回开头

在写入完成后,通过seek方法把文件指针重置到文件起始位置,再进行读取。需要修改两处:

  1. 将文件句柄声明为可变(mut),因为seek需要可变引用
  2. 调用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 22:45:12