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

如何用serde向RON数组文件追加Action枚举(适配大文件)

向RON数组文件追加Action枚举实例(大文件友好)

核心思路

RON数组的结构是[元素1, 元素2, ...],要追加元素无需加载整个文件,只需定位到末尾的],替换为, 新元素](保持格式对齐)即可。分两种场景处理:空文件初始化、已有文件追加。

1. 空文件初始化

如果文件不存在或为空,直接生成标准的RON数组结构,写入第一个元素:

use ron::ser::{to_string, PrettyConfig};
use std::fs::File;
use std::io::Write;

fn init_actions_file(action: &Action) -> std::io::Result<()> {
    // 统一格式配置,保证缩进和换行一致
    let pretty_cfg = PrettyConfig::new()
        .indentor("  ".to_string())
        .new_line("\n".to_string());
    
    // 序列化单个Action并调整缩进,适配数组格式
    let serialized_action = to_string(action, pretty_cfg)?;
    let array_content = format!("[{}]", serialized_action.replace('\n', "\n  "));
    
    let mut file = File::create("actions.ron")?;
    file.write_all(array_content.as_bytes())?;
    Ok(())
}

2. 向已有数组追加元素

通过文件指针定位到末尾的],跳过可能的换行/空格,写入新元素后重新闭合数组:

use ron::ser::{to_string, PrettyConfig};
use std::fs::OpenOptions;
use std::io::{Seek, SeekFrom, Write};

fn append_action_to_file(action: &Action) -> std::io::Result<()> {
    let mut file = OpenOptions::new()
        .read(true)
        .write(true)
        .open("actions.ron")?;

    let file_len = file.metadata()?.len();
    // 空文件直接调用初始化逻辑
    if file_len == 0 {
        return init_actions_file(action);
    }

    // 从文件末尾倒找闭合方括号`]`的位置
    let mut bracket_pos = file_len - 1;
    loop {
        let mut buf = [0u8; 1];
        file.seek(SeekFrom::Start(bracket_pos))?;
        file.read_exact(&mut buf)?;

        if buf[0] == b']' {
            break;
        } else if bracket_pos == 0 {
            return Err(std::io::Error::new(
                std::io::ErrorKind::InvalidData,
                "目标文件不是合法的RON数组格式",
            ));
        }
        bracket_pos -= 1;
    }

    // 定位到`]`的位置,准备覆盖写入
    file.seek(SeekFrom::Start(bracket_pos))?;

    // 序列化新元素,添加逗号和对齐缩进
    let pretty_cfg = PrettyConfig::new()
        .indentor("  ".to_string())
        .new_line("\n".to_string());
    let serialized_action = to_string(action, pretty_cfg)?;
    let new_element = format!(",\n  {}", serialized_action);

    // 写入新元素和闭合方括号
    file.write_all(new_element.as_bytes())?;
    file.write_all(b"\n]")?;

    Ok(())
}

关键注意事项

  • 格式一致性:始终使用相同的PrettyConfig生成序列化字符串,确保缩进、换行符与数组格式匹配,避免反序列化失败。
  • 并发安全:如果存在多线程/进程写入场景,需添加文件排他锁(可使用fs2 crate的FileExt::lock_exclusive),防止文件结构损坏。
  • 错误防护:代码中加入了格式合法性检查,若文件不是标准RON数组会返回明确错误,避免破坏已有数据。
  • 大文件适配:仅通过文件指针定位操作,无需加载整个文件到内存,完美适配超大文件场景。

内容的提问来源于stack exchange,提问作者dodo

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 04:15:32