示例1解析配置use std::fs; use std::num::ParseIntError; #[derive(Debug)] struct Config { port: u16, host: String, timeout: u64, } #[derive(Debug)] enum ConfigError { ReadFile(String), ParsePort(ParseIntError), ParseTimeout(ParseIntError), MissingHost, } fn load_config(path: str) - ResultConfig, ConfigError { // 读取文件 let content fs::read_to_string(path) .map_err(|e| ConfigError::ReadFile(e.to_string()))?; // 解析配置 let mut port None; let mut host None; let mut timeout None; for line in content.lines() { if let Some((key, value)) line.split_once() { let key key.trim(); let value value.trim(); match key { PORT { port Some(value.parse() .map_err(ConfigError::ParsePort)?); } HOST { host Some(value.to_string()); } TIMEOUT { timeout Some(value.parse() .map_err(ConfigError::ParseTimeout)?); } _ {} } } } Ok(Config { port: port.ok_or(ConfigError::MissingHost)?, host: host.ok_or(ConfigError::MissingHost)?, timeout: timeout.unwrap_or(30), // 默认值 }) } fn main() { match load_config(config.txt) { Ok(config) { println!(配置加载成功: {:?}, config); println!(Server running on {}:{} 超时{}, config.host, config.port,config.timeout); } Err(e) { println!(配置加载失败: {:?}, e); } } }config.txt文件内容为PORT8080HOST127.0.0.1TIMEOUT60输出结果为示例2用户输入验证use std::io::{self, Write}; fn read_number(prompt: str) - Resulti32, String { print!({}, prompt); io::stdout().flush().unwrap(); let mut input String::new(); io::stdin().read_line(mut input) .map_err(|e| format!(读取输入失败: {}, e))?; let trimmed input.trim(); if trimmed.is_empty() { return Err(输入不能为空.to_string()); } trimmed.parse() .map_err(|_| format!({} 不是有效的数字, trimmed)) } fn main() { // 使用循环重试 let number loop { match read_number(请输入一个数字: ) { Ok(n) break n, Err(e) { println!(错误: {}请重新输入, e); } } }; println!(你输入的数字是: {}, number); }验证结果示例3链式调用与 Option#[derive(Debug)] struct User { id: u32, name: String, email: OptionString, age: Optionu32, } impl User { fn new(id: u32, name: str) - Self { User { id, name: name.to_string(), email: None, age: None, } } // 设置邮箱 fn set_email(mut self, email: str) - mut Self { self.email Some(email.to_string()); self } // 设置年龄 fn set_age(mut self, age: u32) - mut Self { self.age Some(age); self } // 获取年龄显示信息 fn age_info(self) - String { self.age .map(|a| format!({} 岁, a)) .unwrap_or_else(|| 年龄未设置.to_string()) } // 获取邮箱显示信息 fn email_info(self) - String { self.email .as_ref() .map(|e| format!(邮箱: {}, e)) .unwrap_or_else(|| 未设置邮箱.to_string()) } } fn main() { let mut user User::new(1, Alice); user.set_email(aliceexample.com) .set_age(25); println!(用户: {}, user.name); println!({}, user.email_info()); println!({}, user.age_info()); // 使用 Option 处理可选字段 let maybe_age user.age; if let Some(age) maybe_age { if age 18 { println!({} 是成年人, user.name); } } }结果示例4桌面图标自动整理use std::fs; use std::path::{Path, PathBuf}; use std::io::{self, Write}; use std::time::SystemTime; use serde::{Deserialize, Serialize}; /// 获取当前时间戳字符串 fn get_timestamp() - String { let duration SystemTime::now() .duration_since(SystemTime::UNIX_EPOCH) .unwrap(); let secs duration.as_secs(); format!({}, secs) } /// 获取文件时间戳字符串用于文件名 fn get_file_timestamp() - String { let duration SystemTime::now() .duration_since(SystemTime::UNIX_EPOCH) .unwrap(); let secs duration.as_secs(); format!({}, secs) } /// 分类规则配置 #[derive(Debug, Serialize, Deserialize, Clone)] struct CategoryRule { /// 分类名称 name: String, /// 文件夹名称 folder_name: String, /// 文件扩展名列表 extensions: VecString, } /// 默认分类规则 fn default_rules() - VecCategoryRule { vec![ CategoryRule { name: 文档.to_string(), folder_name: 文档.to_string(), extensions: vec![ doc.to_string(), docx.to_string(), pdf.to_string(), txt.to_string(), xls.to_string(), xlsx.to_string(), ppt.to_string(), pptx.to_string(), md.to_string(), csv.to_string(), rtf.to_string(), odt.to_string(), ], }, CategoryRule { name: 图片.to_string(), folder_name: 图片.to_string(), extensions: vec![ jpg.to_string(), jpeg.to_string(), png.to_string(), gif.to_string(), bmp.to_string(), svg.to_string(), ico.to_string(), webp.to_string(), tiff.to_string(), raw.to_string(), psd.to_string(), ], }, CategoryRule { name: 视频.to_string(), folder_name: 视频.to_string(), extensions: vec![ mp4.to_string(), avi.to_string(), mkv.to_string(), mov.to_string(), wmv.to_string(), flv.to_string(), webm.to_string(), m4v.to_string(), rmvb.to_string(), rm.to_string(), 3gp.to_string(), ], }, CategoryRule { name: 音频.to_string(), folder_name: 音频.to_string(), extensions: vec![ mp3.to_string(), wav.to_string(), flac.to_string(), aac.to_string(), ogg.to_string(), wma.to_string(), m4a.to_string(), ape.to_string(), mid.to_string(), ], }, CategoryRule { name: 压缩包.to_string(), folder_name: 压缩包.to_string(), extensions: vec![ zip.to_string(), rar.to_string(), 7z.to_string(), tar.to_string(), gz.to_string(), bz2.to_string(), xz.to_string(), iso.to_string(), dmg.to_string(), ], }, CategoryRule { name: 程序.to_string(), folder_name: 程序.to_string(), extensions: vec![ exe.to_string(), msi.to_string(), bat.to_string(), cmd.to_string(), lnk.to_string(), appx.to_string(), appxbundle.to_string(), ], }, CategoryRule { name: 代码.to_string(), folder_name: 代码.to_string(), extensions: vec![ py.to_string(), js.to_string(), ts.to_string(), html.to_string(), css.to_string(), java.to_string(), cpp.to_string(), c.to_string(), h.to_string(), rs.to_string(), go.to_string(), rb.to_string(), php.to_string(), json.to_string(), xml.to_string(), yaml.to_string(), yml.to_string(), toml.to_string(), ], }, ] } /// 文件移动记录用于撤销 #[derive(Debug, Serialize, Deserialize)] struct MoveRecord { source: PathBuf, destination: PathBuf, timestamp: String, } /// 撤销日志 #[derive(Debug, Serialize, Deserialize)] struct UndoLog { records: VecMoveRecord, } impl UndoLog { fn new() - Self { UndoLog { records: Vec::new(), } } fn add_record(mut self, source: PathBuf, destination: PathBuf) { self.records.push(MoveRecord { source, destination, timestamp: get_timestamp(), }); } fn save(self, path: Path) - io::Result() { let json serde_json::to_string_pretty(self)?; fs::write(path, json)?; Ok(()) } fn load(path: Path) - io::ResultSelf { let content fs::read_to_string(path)?; let log: UndoLog serde_json::from_str(content)?; Ok(log) } fn is_empty(self) - bool { self.records.is_empty() } fn clear(mut self) { self.records.clear(); } } /// 获取桌面路径 fn get_desktop_path() - PathBuf { dirs::desktop_dir().expect(无法获取桌面路径) } /// 获取配置目录 fn get_config_dir() - PathBuf { let config_dir dirs::config_dir().expect(无法获取配置目录); config_dir.join(windows-tubiao) } /// 获取配置文件路径 fn get_config_path() - PathBuf { get_config_dir().join(rules.json) } /// 获取撤销日志路径 fn get_undo_log_path() - PathBuf { get_config_dir().join(undo_log.json) } /// 加载分类规则 fn load_rules() - VecCategoryRule { let config_path get_config_path(); if config_path.exists() { match fs::read_to_string(config_path) { Ok(content) { match serde_json::from_str(content) { Ok(rules) { println!(已从配置文件加载分类规则); return rules; } Err(e) { eprintln!(配置文件解析失败: {}, 使用默认规则, e); } } } Err(e) { eprintln!(读取配置文件失败: {}, 使用默认规则, e); } } } default_rules() } /// 保存分类规则 fn save_rules(rules: [CategoryRule]) - io::Result() { let config_dir get_config_dir(); fs::create_dir_all(config_dir)?; let config_path get_config_path(); let json serde_json::to_string_pretty(rules)?; fs::write(config_path, json)?; Ok(()) } /// 分类文件 fn categorize_file(file_path: Path, rules: [CategoryRule]) - OptionString { if let Some(ext) file_path.extension() { let ext_str ext.to_string_lossy().to_lowercase(); for rule in rules { if rule.extensions.contains(ext_str) { return Some(rule.folder_name.clone()); } } } None } /// 扫描桌面文件 fn scan_desktop_files(desktop_path: Path) - VecPathBuf { let mut files Vec::new(); if let Ok(entries) fs::read_dir(desktop_path) { for entry in entries { if let Ok(entry) entry { let path entry.path(); // 只处理文件跳过目录和系统文件 if path.is_file() { // 跳过隐藏文件 if let Some(name) path.file_name() { let name_str name.to_string_lossy(); if !name_str.starts_with(.) !name_str.starts_with($) { files.push(path); } } } } } } files } /// 执行整理 fn organize_desktop(rules: [CategoryRule]) - io::ResultUndoLog { let desktop_path get_desktop_path(); let files scan_desktop_files(desktop_path); if files.is_empty() { println!(桌面上没有需要整理的文件); return Ok(UndoLog::new()); } println!(\n扫描到 {} 个文件开始整理...\n, files.len()); let mut undo_log UndoLog::new(); let mut categorized_count 0; let mut uncategorized_count 0; for file_path in files { if let Some(category) categorize_file(file_path, rules) { // 创建分类文件夹 let category_dir desktop_path.join(category); if !category_dir.exists() { fs::create_dir_all(category_dir)?; } // 移动文件 let file_name file_path.file_name().unwrap(); let dest_path category_dir.join(file_name); // 如果目标文件已存在添加时间戳避免覆盖 let final_dest if dest_path.exists() { let stem file_path.file_stem().unwrap().to_string_lossy(); let ext file_path.extension().unwrap().to_string_lossy(); let timestamp get_file_timestamp(); let new_name format!({}_{}.{}, stem, timestamp, ext); category_dir.join(new_name) } else { dest_path }; match fs::rename(file_path, final_dest) { Ok(_) { undo_log.add_record(file_path.clone(), final_dest); categorized_count 1; println!( [{}] - {}/, file_path.file_name().unwrap().to_string_lossy(), category); } Err(e) { eprintln!( 移动失败 {}: {}, file_path.file_name().unwrap().to_string_lossy(), e); } } } else { uncategorized_count 1; } } println!(\n整理完成!); println!( 已分类: {} 个文件, categorized_count); println!( 未分类: {} 个文件, uncategorized_count); Ok(undo_log) } /// 撤销整理 fn undo_organize() - io::Result() { let undo_log_path get_undo_log_path(); if !undo_log_path.exists() { println!(没有可撤销的操作记录); return Ok(()); } let mut undo_log UndoLog::load(undo_log_path)?; if undo_log.is_empty() { println!(没有可撤销的操作记录); return Ok(()); } let total undo_log.records.len(); println!(\n开始撤销 {} 个文件移动...\n, total); let mut success_count 0; let mut fail_count 0; // 从后往前撤销最新的操作先撤销 for record in undo_log.records.iter().rev() { // 确保源目录存在 if let Some(parent) record.source.parent() { if !parent.exists() { fs::create_dir_all(parent)?; } } if record.destination.exists() { match fs::rename(record.destination, record.source) { Ok(_) { success_count 1; println!( 已恢复: {}, record.source.file_name().unwrap().to_string_lossy()); } Err(e) { fail_count 1; eprintln!( 恢复失败 {}: {}, record.source.file_name().unwrap().to_string_lossy(), e); } } } else { fail_count 1; eprintln!( 文件不存在: {}, record.destination.display()); } } println!(\n撤销完成!); println!( 成功: {} 个文件, success_count); println!( 失败: {} 个文件, fail_count); // 清空撤销日志 undo_log.clear(); undo_log.save(undo_log_path)?; Ok(()) } /// 显示当前分类规则 fn show_rules(rules: [CategoryRule]) { println!(\n当前分类规则:); println!({}, ─.repeat(50)); for (i, rule) in rules.iter().enumerate() { println!({}. {} ({}), i 1, rule.name, rule.folder_name); println!( 扩展名: {}, rule.extensions.join(, )); println!(); } } /// 添加自定义分类规则 fn add_rule(rules: mut VecCategoryRule, name: String, folder_name: String, extensions: VecString) - io::Result() { // 检查是否已存在同名规则 if rules.iter().any(|r| r.name name) { println!(已存在同名规则: {}, name); return Ok(()); } rules.push(CategoryRule { name, folder_name, extensions, }); save_rules(rules)?; println!(规则添加成功!); Ok(()) } /// 删除分类规则 fn remove_rule(rules: mut VecCategoryRule, index: usize) - io::Result() { if index 0 || index rules.len() { println!(无效的规则索引); return Ok(()); } let removed rules.remove(index - 1); save_rules(rules)?; println!(已删除规则: {}, removed.name); Ok(()) } /// 显示主菜单 fn show_menu() { println!(\n╔════════════════════════════════════════╗); println!(║ Windows 桌面图标归类整理工具 ║); println!(╠════════════════════════════════════════╣); println!(║ 1. 一键整理桌面 ║); println!(║ 2. 撤销上次整理 ║); println!(║ 3. 查看分类规则 ║); println!(║ 4. 添加自定义规则 ║); println!(║ 5. 删除分类规则 ║); println!(║ 6. 恢复默认规则 ║); println!(║ 7. 查看桌面文件 ║); println!(║ 0. 退出 ║); println!(╚════════════════════════════════════════╝); print!(\n请选择操作 [0-7]: ); io::stdout().flush().unwrap(); } /// 读取用户输入 fn read_input() - String { let mut input String::new(); io::stdin().read_line(mut input).unwrap(); input.trim().to_string() } /// 一键整理桌面 fn cmd_organize(rules: [CategoryRule]) { println!(\n正在扫描桌面...); match organize_desktop(rules) { Ok(undo_log) { if !undo_log.is_empty() { // 保存撤销日志 let undo_log_path get_undo_log_path(); if let Err(e) undo_log.save(undo_log_path) { eprintln!(保存撤销日志失败: {}, e); } } } Err(e) { eprintln!(整理失败: {}, e); } } } /// 查看桌面文件 fn cmd_show_desktop_files() { let desktop_path get_desktop_path(); let files scan_desktop_files(desktop_path); if files.is_empty() { println!(\n桌面上没有文件); return; } println!(\n桌面文件列表 (共 {} 个):, files.len()); println!({}, ─.repeat(50)); for (i, file) in files.iter().enumerate() { println!({}. {}, i 1, file.file_name().unwrap().to_string_lossy()); } } fn main() { println!(Windows 桌面图标归类整理工具); println!(版本: 0.1.0\n); // 确保配置目录存在 let config_dir get_config_dir(); if let Err(e) fs::create_dir_all(config_dir) { eprintln!(创建配置目录失败: {}, e); } let mut rules load_rules(); loop { show_menu(); let choice read_input(); match choice.as_str() { 1 { cmd_organize(rules); } 2 { if let Err(e) undo_organize() { eprintln!(撤销失败: {}, e); } } 3 { show_rules(rules); } 4 { println!(\n添加自定义分类规则); println!({}, ─.repeat(30)); print!(分类名称: ); io::stdout().flush().unwrap(); let name read_input(); print!(文件夹名称: ); io::stdout().flush().unwrap(); let folder_name read_input(); print!(文件扩展名 (用逗号分隔如: jpg,png,gif): ); io::stdout().flush().unwrap(); let ext_input read_input(); let extensions: VecString ext_input .split(,) .map(|s| s.trim().to_lowercase()) .filter(|s| !s.is_empty()) .collect(); if name.is_empty() || folder_name.is_empty() || extensions.is_empty() { println!(输入不能为空); continue; } if let Err(e) add_rule(mut rules, name, folder_name, extensions) { eprintln!(添加规则失败: {}, e); } } 5 { show_rules(rules); print!(\n请输入要删除的规则序号: ); io::stdout().flush().unwrap(); let index: usize read_input().parse().unwrap_or(0); if let Err(e) remove_rule(mut rules, index) { eprintln!(删除规则失败: {}, e); } } 6 { print!(\n确定要恢复默认规则吗? (y/n): ); io::stdout().flush().unwrap(); let confirm read_input(); if confirm.to_lowercase() y { rules default_rules(); if let Err(e) save_rules(rules) { eprintln!(保存默认规则失败: {}, e); } else { println!(已恢复默认规则); } } } 7 { cmd_show_desktop_files(); } 0 { println!(\n感谢使用再见!); break; } _ { println!(\n无效的选择请重新输入); } } } }