C#中解析特定格式文本字段获取数据的问题
如何解析带不定空格的键值对字符串到C# DTO?
问题描述
我现在拿到这样一段字符串:
var data="frame= 159 fps= 51 q=34.0 size= 512kB time=00:00:05.37 bitrate= 780.3kbits/s dup=3 drop=0 speed=1.72x";
这里的分隔符只有空格,但像frame= 159这类字段的等号后有不定数量的空格,常规的字符串分割(比如data.Split(" "))根本没法用,因为会得到很多空元素。我需要把这些值解析到下面这个DTO里:public class Template { public float Frame {get;set;} public float Fps {get;set;} public string Size {get;set;} public TimeSpan Time {get;set;} public string Bitrate {get;set;} public short Dup {get;set;} public short Drop {get;set;} public string Speed {get;set;} }请问有没有可靠的解析方法?
解决方案:正则表达式匹配(最优)
碰到这种带不定空格的键值对场景,正则表达式是最直接高效的解法——我之前处理ffmpeg输出日志时就用这个方案,完美适配这种格式。
1. 定义正则匹配模式
我们可以用这个模式来捕获所有键=值的组合,不管等号前后有多少空格:
(\w+)\s*=\s*([^\s]+)
(\w+):匹配键名(比如frame、fps),作为第一个捕获组\s*=\s*:匹配等号,前后允许任意数量的空格(包括0个,比如q=34.0这种无空格的情况)([^\s]+):匹配值(直到下一个空格为止),作为第二个捕获组
2. 完整C#解析代码
下面是可直接运行的实现,包含匹配、类型转换和DTO赋值,还做了异常容错:
using System; using System.Text.RegularExpressions; public class Template { public float Frame {get;set;} public float Fps {get;set;} public string Size {get;set;} public TimeSpan Time {get;set;} public string Bitrate {get;set;} public short Dup {get;set;} public short Drop {get;set;} public string Speed {get;set;} } public static class FfmpegOutputParser { public static Template Parse(string input) { var template = new Template(); var regexPattern = @"(\w+)\s*=\s*([^\s]+)"; var matches = Regex.Matches(input, regexPattern); foreach (Match match in matches) { var key = match.Groups[1].Value.ToLower(); var value = match.Groups[2].Value; switch(key) { case "frame": float.TryParse(value, out template.Frame); break; case "fps": float.TryParse(value, out template.Fps); break; case "size": template.Size = value; break; case "time": TimeSpan.TryParse(value, out template.Time); break; case "bitrate": template.Bitrate = value; break; case "dup": short.TryParse(value, out template.Dup); break; case "drop": short.TryParse(value, out template.Drop); break; case "speed": template.Speed = value; break; // 遇到不需要的键(比如示例中的q)直接忽略 } } return template; } } // 使用示例 var data = "frame= 159 fps= 51 q=34.0 size= 512kB time=00:00:05.37 bitrate= 780.3kbits/s dup=3 drop=0 speed=1.72x"; var parsedResult = FfmpegOutputParser.Parse(data); // parsedResult现在就包含所有解析好的字段值了
方案优势
- 适配所有空格情况:不管等号前后有没有空格、有多少空格,都能准确匹配
- 容错性强:用
TryParse避免类型转换失败导致的崩溃 - 扩展性好:如果后续需要解析更多字段,直接在switch里加case就行
备选方案:字符串预处理后分割
如果你不想用正则,也可以先预处理字符串再分割,不过这个方案只适合值里没有空格的场景:
public static Template ParseWithPreprocessing(string input) { // 先把所有"= "替换成"=",消除等号后的空格 var processedInput = input.Replace("= ", "="); // 按空格分割,同时移除空元素 var keyValueParts = processedInput.Split(new[] {' '}, StringSplitOptions.RemoveEmptyEntries); var template = new Template(); foreach (var part in keyValueParts) { var keyValue = part.Split('='); if (keyValue.Length != 2) continue; var key = keyValue[0].ToLower(); var value = keyValue[1]; // 下面的switch逻辑和正则方案一致,此处省略重复代码 switch(key) { case "frame": float.TryParse(value, out template.Frame); break; // ...其他字段的处理 } } return template; }
注意:如果你的值字段后续可能包含空格(比如某些特殊格式的bitrate),这个方案就会失效,所以更推荐正则方案。
内容的提问来源于stack exchange,提问作者Varun
相关产品推荐
相关产品推荐

