C# WinForm如何实现按用户分组排序登录日志并按指定格式输出
实现方案
你不需要使用两个独立的平行数组存储用户名和登录时间,这种结构做分组操作效率低,还容易出现索引错位的问题。WinForm项目默认集成的LINQ分组功能或者字典结构,都可以很方便实现你要的按用户分组输出日志的需求。
现有代码的潜在问题
你当前按|拆分字符串时,因为日志末尾自带一个|,拆分后最后一个元素是空字符串,直接访问Split(',')[1]会触发索引越界异常,需要在拆分时直接过滤空条目。
推荐实现代码(LINQ版,代码最简洁)
确保你的代码文件已经引用了System.Linq和System.Text命名空间(WinForm项目默认已引入相关程序集,直接加using即可):
using System; using System.Linq; using System.IO; using System.Text; // 日志处理逻辑 string logContent = File.ReadAllText(@"D:\Docs\Enter.log"); // 拆分日志并过滤空条目,组装为单条日志结构 var logGroups = logContent.Split('|', StringSplitOptions.RemoveEmptyEntries) .Select(logItem => { string[] itemParts = logItem.Split(','); return (UserName: itemParts[0].Trim(), LoginTime: itemParts[1].Trim()); }) // 按用户名分组,按用户名升序排列分组 .GroupBy(item => item.UserName) .OrderBy(group => group.Key); // 拼接最终输出内容 StringBuilder outputBuilder = new StringBuilder(); foreach (var group in logGroups) { outputBuilder.AppendLine($"{group.Key}:"); // 组内时间按登录先后排序后逐行写入 foreach (string time in group.Select(i => i.LoginTime).OrderBy(t => DateTime.Parse(t))) { outputBuilder.AppendLine(time); } // 不同用户分组之间加空行分隔 outputBuilder.AppendLine(); } // 移除末尾多余空行,得到最终结果 string finalResult = outputBuilder.ToString().TrimEnd();
得到的finalResult格式和你给出的示例完全一致,可以直接赋值给WinForm的文本框控件展示,或者写入文件。
无LINQ的字典实现方案
如果你不想用LINQ,可以用Dictionary<string, List<string>>存储分组结果,逻辑也很清晰:
using System; using System.Collections.Generic; using System.IO; using System.Text; using System.Linq; string logContent = File.ReadAllText(@"D:\Docs\Enter.log"); Dictionary<string, List<string>> userLogMap = new Dictionary<string, List<string>>(); string[] logItems = logContent.Split('|', StringSplitOptions.RemoveEmptyEntries); foreach (string item in logItems) { string[] parts = item.Split(','); string userName = parts[0].Trim(); string loginTime = parts[1].Trim(); // 字典中不存在对应用户时,先初始化条目 if (!userLogMap.ContainsKey(userName)) { userLogMap.Add(userName, new List<string>()); } userLogMap[userName].Add(loginTime); } // 拼接输出 StringBuilder outputBuilder = new StringBuilder(); // 按用户名排序后遍历 foreach (string userName in userLogMap.Keys.OrderBy(k => k)) { outputBuilder.AppendLine($"{userName}:"); // 组内时间排序 foreach (string time in userLogMap[userName].OrderBy(t => DateTime.Parse(t))) { outputBuilder.AppendLine(time); } outputBuilder.AppendLine(); } string finalResult = outputBuilder.ToString().TrimEnd();
关键点说明
- 用
StringBuilder拼接字符串比直接用string做+=拼接效率高很多,日志量较大时不会出现UI卡顿 - 所有时间在输出前都转成
DateTime做排序,避免字符串排序导致的时间顺序错误 - 两种实现都自动处理了日志末尾空条目的问题,不会抛出索引越界异常
内容的提问来源于stack exchange,提问作者Javad-M
相关产品推荐
相关产品推荐

