当前位置: 首页 > news >正文

Rust:如何访问 *.ini 配置文件?

在 Rust 中读写 INI 文件,推荐使用成熟的 configparserini 库。下面提供两种实现方案(基础和高阶),包含完整代码示例:


方案一:使用 configparser(功能更强大)

1. 添加依赖
[dependencies]
configparser = "3.0.2"
anyhow = "1.0"  # 可选,用于错误处理
2. 读写 INI 文件完整示例
use anyhow::Result;
use configparser::ini::Ini;fn main() -> Result<()> {// ===== 写入 INI 文件 =====let mut config = Ini::new();// 添加全局值config.set("", "debug", Some("true"));config.set("", "timeout", Some("30"));// 添加带节的配置config.set("server", "host", Some("localhost"));config.set("server", "port", Some("8080"));// 添加另一个节config.set("user", "name", Some("Alice"));config.set("user", "active", Some("yes"));// 写入文件(支持注释)config.write_to_path("config.ini")?;// ===== 读取 INI 文件 =====let mut config_read = Ini::new();config_read.load("config.ini")?;// 读取全局值let debug = config_read.getbool("", "debug")?.unwrap();println!("Debug enabled: {}", debug);// 读取带节的值let port: i32 = config_read.get("server", "port")?.parse().unwrap_or(8080);println!("Server port: {}", port);// 读取整段if let Some(user_section) = config_read.sections().get("user") {println!("User name: {}", user_section["name"]);}// 更新并保存config_read.set("user", "active", Some("no"));config_read.write_to_path("config.ini")?;Ok(())
}
3. 高级特性
// 1. 自定义解析类型
let timeout: u64 = config_read.getuint("", "timeout")?.unwrap();// 2. 添加注释
config.set_comment("", "debug", vec!["; Global debug flag"]);
config.set_section_comment("user", vec!["", "# User settings", ""]);// 3. 多行值处理
config.set("multiline", "description", Some("这是\\n多行\\n值"));
let desc = config.get("multiline", "description").unwrap();
// => "这是\n多行\n值"// 4. 错误处理强化
match config.get("invalid_section", "key") {Ok(Some(val)) => println!("Value: {}", val),Ok(None) => println!("Key not found"),Err(e) => eprintln!("Error: {}", e),
}

方案二:使用 ini(轻量级)

1. 添加依赖
[dependencies]
ini = "3.0.1"
2. 基础读写操作
use ini::Ini;
use anyhow::Result;fn main() -> Result<()> {// ===== 创建新INI文件 =====let mut conf = Ini::new();// 添加全局属性conf.with_general_section().set("debug", "true").set("timeout", "30");// 添加节conf.with_section(Some("server")).set("host", "localhost").set("port", "8080");// 添加带注释的节conf.with_section(Some("user")).set("name", "Alice").set("active", "yes");// 写入文件conf.write_to_file("config.ini")?;// ===== 读取文件 =====let conf_read = Ini::load_from_file("config.ini")?;// 读取全局属性if let Some(debug_val) = conf_read.general_section().get("debug") {println!("Debug: {}", debug_val);}// 读取具体节if let Some(user) = conf_read.section(Some("user")) {let name = user.get("name").unwrap_or_default();println!("User name: {}", name);}// 遍历所有节for (sec, props) in &conf_read {println!("[{sec}]");for (key, value) in props.iter() {println!("{key} = {value}");}}Ok(())
}
3. 自定义配置
// 1. 自定义分隔符(默认为 =)
let mut conf = Ini::new_custom();
conf.section_mut(Some("section")).insert_with_separator("key", "value", ":");
// => key: value// 2. 保留注释
let conf = Ini::load_from_file("config.ini")?;
println!("原始注释: {:#?}", conf);// 3. 复杂数据类型
conf.with_section(Some("database")).set("port", 5432.to_string()).set("active", true.to_string());

功能对比表

特性configparserini
类型转换✅ (getint, getbool 等)
注释处理✅ (完整支持)✅ (部分支持)
多行值
默认值支持
文件自动重载
错误处理⭐⭐⭐⭐⭐⭐
性能⭐⭐⭐⭐⭐⭐⭐
文件大小限制

错误处理最佳实践

use configparser::ini::IniError;fn load_config() -> Result<(), IniError> {let mut config = Ini::new();// 优雅处理缺失值let host = config.get("server", "host").ok_or(IniError::MissingSectionOrKey("server.host".into()))?;// 强制类型转换let port: u16 = config.get("server", "port").and_then(|s| s.parse().ok()).ok_or(IniError::ValueError("Invalid port format".into()))?;println!("Connecting to {host}:{port}");Ok(())
}

INI 文件标准示例

; 全局配置
debug = true
timeout = 30[server]
# 服务器地址
host = 127.0.0.1
port = 8080  ; HTTP 端口[database]
user = dbadmin
password = "secret!@#$"

替代方案:手动解析(不推荐)

对于简单需求可自行处理:

use std::fs;
use anyhow::Context;fn parse_ini(path: &str) -> anyhow::Result<()> {let contents = fs::read_to_string(path)?;let mut current_section = "default";for line in contents.lines() {let line = line.trim();if line.is_empty() || line.starts_with(';') || line.starts_with('#') {continue;}if let Some(section) = line.strip_prefix('[').and_then(|s| s.strip_suffix(']')) {current_section = section;continue;}if let Some((key, value)) = line.split_once('=') {let key = key.trim();let value = value.trim();println!("Section: {current_section}, Key: {key}, Value: {value}");}}Ok(())
}

注意:手动解析无法处理复杂情况(如转义字符、多行值等),建议优先使用现成库。

根据需求选择库:

  • 需要复杂值类型转换 → 选 configparser
  • 只需要基本键值读取 → 选 ini
  • 需要集成系统配置 → 考虑 confy (基于 serde)
http://www.dtcms.com/a/313228.html

相关文章:

  • 【项目日志|苍穹外卖】 Day1:项目环境搭建与架构设计
  • 反向代理+网关部署架构
  • Java学习第一百零二部分——API网关
  • Claude Code入门学习笔记(五)--Claude Code命令行输入
  • 大白话讲解MCP
  • 多种单文件版分析型数据库调用底层函数对比
  • [Oracle] TO_DATE()函数
  • cs285 lecture13
  • 手机端使用表格填写表单问题
  • 复现YOLOV5+训练指定数据集
  • STM32-ESP8266通过MQTT与阿里云通讯
  • MySQL连接算法和小表驱动大表的原理
  • 李宏毅深度学习教程 第8-9章 生成模型+扩散模型
  • 【Django】-7- 实现注册功能
  • 09.Redis 常用命令
  • Android 之 蓝牙通信(2.0 经典)
  • 【硬件-笔试面试题】硬件/电子工程师,笔试面试题-58,(知识点:硬件产品的功率优化)
  • C++中多线程和互斥锁的基本使用
  • 【RH124 问答题】第 8 章 监控和管理 Linux 进程
  • Baumer工业相机堡盟工业相机如何通过YoloV8深度学习模型实现实时食物水果的检测识别(C#代码UI界面版)
  • 使用 Spring Initializr 生成项目结构:Java 开发效率提升指南
  • 【QT】常⽤控件详解(二)windowOpacitycursorfontsetToolTipfocusPolicystyleSheet
  • 大语言模型涉及的一些概念(持续更新)
  • VisualStudio的一些开发经验
  • 思二勋:数字资产化与资产数权化是RWA运作的核心逻辑
  • AtCoder Beginner Contest 417
  • MySQL事务与存储引擎的学习(一)
  • Docker国内镜像列表
  • Effective C++ 条款19: 设计class犹如设计type
  • Python从入门到精通计划Day02: Python语法探秘:当现代艺术遇到古典音乐