在C#中解析指定格式.dat文件并映射至DTO的技术问询
如何在C#中解析特定格式的.dat文件并转换为DTO对象
我来帮你一步步解决这个问题——解析这种以关键字驱动、制表符分隔的.dat文件并转成C# DTO其实不难,我们可以分几个步骤来实现:
第一步:定义对应的DTO类
首先,我们需要创建一个DTO类来映射文件中的各个字段,根据你给出的格式,我们可以这样定义:
public class ItemDto { // VNUM对应两个数值 public (int Min, int Max) Vnum { get; set; } // NAME是字符串 public string Name { get; set; } = string.Empty; // INDEX、TYPE、FLAG等是整数数组 public int[] Index { get; set; } = Array.Empty<int>(); public int[] Type { get; set; } = Array.Empty<int>(); public int[] Flag { get; set; } = Array.Empty<int>(); public int[] Data { get; set; } = Array.Empty<int>(); public int[] Buff { get; set; } = Array.Empty<int>(); // LINEDESC对应一个ID和描述字符串 public (int Id, string Desc) LineDesc { get; set; } }
第二步:读取文件并分割条目
你的文件中每个条目用#======================================================== 作为分隔符,我们先读取整个文件内容,然后分割成单个条目:
// 替换成你的.dat文件路径 var filePath = @"C:\your-path\items.dat"; var fileContent = File.ReadAllText(filePath); // 定义条目分隔符 var entrySeparator = "#======================================================== "; // 分割成单个条目,移除空条目 var entries = fileContent.Split(new[] { entrySeparator }, StringSplitOptions.RemoveEmptyEntries);
第三步:解析单个条目为DTO
接下来我们需要编写一个解析方法,把每个条目字符串转换成ItemDto对象。核心思路是:
- 把条目按制表符分割成一个个token
- 遍历token,根据关键字(VNUM、NAME等)来收集对应的值
private static ItemDto ParseEntry(string entry) { var dto = new ItemDto(); // 按制表符分割所有token,移除空项 var tokens = entry.Split('\t', StringSplitOptions.RemoveEmptyEntries); int currentIndex = 0; while (currentIndex < tokens.Length) { switch (tokens[currentIndex]) { case "VNUM": // VNUM后跟着2个整数 if (currentIndex + 2 < tokens.Length && int.TryParse(tokens[currentIndex+1], out var vnumMin) && int.TryParse(tokens[currentIndex+2], out var vnumMax)) { dto.Vnum = (vnumMin, vnumMax); currentIndex += 3; // 跳过VNUM和两个值 } else { // 解析失败时跳过当前关键字,也可以添加日志记录 currentIndex++; } break; case "NAME": // NAME后跟着1个字符串 if (currentIndex + 1 < tokens.Length) { dto.Name = tokens[currentIndex+1]; currentIndex += 2; } else { currentIndex++; } break; case "INDEX": case "TYPE": case "FLAG": case "DATA": case "BUFF": // 这些关键字后跟着若干整数,直到遇到下一个关键字 var intValues = new List<int>(); currentIndex++; // 跳过当前关键字 while (currentIndex < tokens.Length && !IsKeyword(tokens[currentIndex])) { if (int.TryParse(tokens[currentIndex], out var val)) { intValues.Add(val); } currentIndex++; } // 根据关键字赋值到对应的属性 switch (tokens[currentIndex - intValues.Count - 1]) { case "INDEX": dto.Index = intValues.ToArray(); break; case "TYPE": dto.Type = intValues.ToArray(); break; case "FLAG": dto.Flag = intValues.ToArray(); break; case "DATA": dto.Data = intValues.ToArray(); break; case "BUFF": dto.Buff = intValues.ToArray(); break; } break; case "LINEDESC": // LINEDESC后跟着1个整数和1个字符串 if (currentIndex + 2 < tokens.Length && int.TryParse(tokens[currentIndex+1], out var ldId)) { dto.LineDesc = (ldId, tokens[currentIndex+2]); currentIndex += 3; } else { currentIndex++; } break; case "END": // 遇到END标记,直接结束解析 currentIndex = tokens.Length; break; default: // 未知关键字,直接跳过 currentIndex++; break; } } return dto; } // 辅助方法:判断当前token是否是定义的关键字 private static bool IsKeyword(string token) { var keywords = new HashSet<string> { "VNUM", "NAME", "INDEX", "TYPE", "FLAG", "DATA", "BUFF", "LINEDESC", "END" }; return keywords.Contains(token); }
第四步:批量解析所有条目
最后,我们遍历所有分割后的条目,调用解析方法得到完整的DTO列表:
var itemDtos = new List<ItemDto>(); foreach (var entry in entries) { var item = ParseEntry(entry); itemDtos.Add(item); } // 现在itemDtos里就是所有解析完成的对象了
一些注意事项
- 制表符确认:确保你的.dat文件确实是用**制表符(
\t)**分隔字段,不是空格——你明确提到了这一点,所以解析时一定要用\t分割,不要用空格。 - 错误处理:上面的代码做了基本的解析容错,但在实际项目中,建议添加日志记录(比如解析失败的token、条目内容),方便排查格式异常的情况。
- 扩展性:如果以后文件格式新增了关键字,只需要扩展
switch语句和IsKeyword方法中的关键字集合即可。
内容的提问来源于stack exchange,提问作者PepB




