基于C# System Speech实现CSV文件夹别名语音打开的技术问询
解决方案:基于CSV配置的语音打开文件夹功能
核心思路
用**Dictionary<string, string>**存储CSV中的别名-路径映射,既方便读取配置,又能快速通过别名匹配对应路径,比数组索引匹配更高效。同时动态生成语音识别语法,彻底替代硬编码指令。
步骤实现
1. 读取CSV配置文件
读取CSV内容,将每行拆分为别名和路径,存入Dictionary:
// 假设CSV文件放在程序目录下的FolderAliases.csv var aliasPathMap = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); foreach (var line in File.ReadAllLines("FolderAliases.csv")) { var parts = line.Split(',', StringSplitOptions.RemoveEmptyEntries); if (parts.Length == 2) { aliasPathMap[parts[0].Trim()] = parts[1].Trim(); } }
2. 动态构建语音识别语法
从Dictionary的键(别名)生成可选指令,构建「打开{别名}文件夹」的语法规则:
// 生成所有别名对应的选项 var aliasChoices = new Choices(aliasPathMap.Keys.ToArray()); // 组装语法模板 var grammarBuilder = new GrammarBuilder(); grammarBuilder.Append("打开"); grammarBuilder.Append(aliasChoices); grammarBuilder.Append("文件夹"); // 加载语法到识别引擎 listener.LoadGrammarAsync(new Grammar(grammarBuilder));
3. 处理语音识别事件
识别到指令后,提取别名,从Dictionary中取路径并打开资源管理器:
private void Speech_recognize(object? sender, SpeechRecognizedEventArgs e) { // 提取识别结果中的别名(语法模板的第2个元素) if (e.Result.Words.Count >= 2) { string alias = e.Result.Words[1].Text; if (aliasPathMap.TryGetValue(alias, out string? targetPath)) { Process.Start(new ProcessStartInfo(targetPath) { UseShellExecute = true }); } } }
完整代码示例
using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Speech.Recognition; using System.Linq; namespace WinFormsApp2 { public partial class Form1 : Form { private SpeechRecognitionEngine _listener = new SpeechRecognitionEngine(); private Dictionary<string, string> _aliasPathMap = new(StringComparer.OrdinalIgnoreCase); public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { // 读取CSV配置 LoadFolderAliases(); // 配置语音识别引擎 _listener.SetInputToDefaultAudioDevice(); _listener.SpeechRecognized += Speech_recognize; // 动态加载语法 LoadRecognitionGrammar(); } private void LoadFolderAliases() { string csvPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "FolderAliases.csv"); if (!File.Exists(csvPath)) { // 可添加文件不存在的提示逻辑 return; } foreach (var line in File.ReadAllLines(csvPath)) { var parts = line.Split(',', StringSplitOptions.RemoveEmptyEntries); if (parts.Length == 2) { _aliasPathMap[parts[0].Trim()] = parts[1].Trim(); } } } private void LoadRecognitionGrammar() { if (_aliasPathMap.Count == 0) return; var aliasChoices = new Choices(_aliasPathMap.Keys.ToArray()); var grammarBuilder = new GrammarBuilder(); grammarBuilder.Append("打开"); grammarBuilder.Append(aliasChoices); grammarBuilder.Append("文件夹"); _listener.LoadGrammarAsync(new Grammar(grammarBuilder)); } private void Speech_recognize(object? sender, SpeechRecognizedEventArgs e) { if (e.Result.Words.Count >= 2) { string alias = e.Result.Words[1].Text; if (_aliasPathMap.TryGetValue(alias, out string? targetPath)) { try { Process.Start(new ProcessStartInfo(targetPath) { UseShellExecute = true }); } catch (Exception ex) { // 可添加错误提示逻辑,比如路径不存在等 Debug.WriteLine($"打开失败: {ex.Message}"); } } } } private void listen_Click(object sender, EventArgs e) { _listener.RecognizeAsync(RecognizeMode.Multiple); listen.Enabled = false; stop.Enabled = true; } private void stop_Click(object sender, EventArgs e) { _listener.RecognizeAsyncCancel(); listen.Enabled = true; stop.Enabled = false; } } }
关键说明
- Dictionary映射优势:相比数组,通过别名直接查找路径的时间复杂度为O(1),效率更高,无需维护索引对应关系。
- 大小写兼容:
StringComparer.OrdinalIgnoreCase确保语音识别的别名(如"temp"和"Temp")都能匹配到对应路径。 - 动态更新:CSV文件修改后,重启程序即可加载新的别名指令,无需改动代码。
内容的提问来源于stack exchange,提问作者daftcranberry2
相关产品推荐
相关产品推荐

