外卖店加载程序:文本文件转对象实例解析问题求助
外卖店加载程序解析不完整问题修复
问题背景
开发外卖店加载程序,需将以下格式的文本文件解析为对象实例,实现下单、编辑订单功能:
Name:JustNom FastFood Toppings:[<cheese,80>,<pepperoni,120>,<tomato sauce,40>,<ham,150>,<mushroom,80>] Garnishes:[<cheese,100>,<fried onions, 80>,<bacon,150>] Pizza:<Name:Margherita,Toppings:[tomato sauce, cheese],Price:500> Pizza:<Name:Ham and Mushroom,Toppings:[tomato sauce, ham, mushroom, cheese],Price:650> Burger:<Name:Plain Burger,Garnishes:[],Price:350> Burger:<Name:Cheese Burger,Garnishes:[cheese],Price:450>
现有代码仅能解析第一部分内容(如仅能解析第一个Topping,其余无法解析),尝试循环Load方法未解决,相关代码如下:
原FileReaderMenu代码
namespace JustNom.Logic { internal class FileReaderMenu : MenuItem { private FileReader _reader; public string menuName { get; set; } public FileReaderMenu(FileReader reader) { _reader = reader; } public override string MenuText() { return "Select a File."; } public override void Select() { StringBuilder sb = new StringBuilder($"{MenuText()}{Environment.NewLine}"); int i = 1; foreach (string file in _reader.paths) { sb.AppendLine($"{i}. {file}"); i++; } Console.WriteLine(sb.ToString()); int selectedIndex = ConsoleHelpers.GetIntegerInRange(1, _reader.paths.Count, MenuText()) - 1; string[] result = File.ReadAllLines(_reader.paths[selectedIndex]); if (result.Length == 0) { Console.WriteLine("Cannot open file - No data found"); } else if (result.Length > 0) { var splitedStringList = new List<List<String>>(); Menu menu = new Menu(menuName); foreach (string file in result) { if (file.StartsWith("Name:")) { menuName = file.Substring("Name:".Length); } string token = file.Substring(0, file.IndexOf(':')); switch (token) { case "Toppings": Topping topping = LoadToppings(file); menu.AddToppings(topping); break; case "Garnishes": Garnish garnish = LoadGarnishes(file); menu.AddGarnish(garnish); break; case "Pizza": Pizza pizza = LoadPizzas(file); menu.AddPizza(pizza); break; case "Burger": Burger burger = LoadBurgers(file); menu.AddBurger(burger); break; } static Topping LoadToppings(string toppings) { int startIndex = toppings.IndexOf('<') + 1; int endIndex = toppings.IndexOf(','); int length = endIndex - startIndex; string name = toppings.Substring(startIndex, length); startIndex = endIndex + 1; endIndex = toppings.IndexOf('>'); length = endIndex - startIndex; string price = toppings.Substring(startIndex, length); return new Topping(name, price); } static Garnish LoadGarnishes(string garnishes) { int startIndex = garnishes.IndexOf('<') + 1; int endIndex = garnishes.IndexOf(','); int length = endIndex - startIndex; string name = garnishes.Substring(startIndex, length); startIndex = endIndex + 1; endIndex = garnishes.IndexOf('>'); length = endIndex - startIndex; string price = garnishes.Substring(startIndex, length); return new Garnish(name, price); } static Pizza LoadPizzas(string pizza) { int startIndex = pizza.IndexOf(':') + 7; int endIndex = pizza.IndexOf(','); int length = endIndex - startIndex; string name = pizza.Substring(startIndex, length); startIndex = endIndex + 11; endIndex = pizza.IndexOf("]"); length = endIndex - startIndex; string toppings = pizza.Substring(startIndex, length); startIndex = endIndex + 1; endIndex = pizza.IndexOf(">>"); length = endIndex - startIndex; string price = pizza.Substring(startIndex, length); return new Pizza(name,toppings, price); } static Burger LoadBurgers(string burger) { int startIndex = burger.IndexOf(':') + 7; int endIndex = burger.IndexOf(','); int length = endIndex - startIndex; string name = burger.Substring(startIndex, length); startIndex = burger.IndexOf('['); endIndex = burger.IndexOf("]"); length = endIndex - startIndex; string garnish = burger.Substring(startIndex, length); startIndex = burger.IndexOf(':'); endIndex = burger.IndexOf(">>"); length = endIndex - startIndex; string price = burger.Substring(startIndex, length); return new Burger(name,garnish, price); } } OrderMenuItem OrderMenu = new OrderMenuItem(menu); OrderMenu.MenuText(); } } } }
原Menu类代码
namespace JustNom.JustNom { internal class Menu { public string Name { get; private set; } private List<Burger> _burgers; private List<Pizza> _pizzas; private List<Garnish> _garnish; private List<Topping> _topping; public IEnumerable<Burger> Burgers { get { return _burgers; } } public IEnumerable<Pizza> Pizzas { get { return _pizzas; } } public IEnumerable<Garnish> Garnish { get { return _garnish; } } public IEnumerable<Topping> Toppings { get { return _topping; } } public Menu(string name) { Name = name; _burgers = new List<Burger>(); _pizzas = new List<Pizza>(); _topping = new List<Topping>(); _garnish = new List<Garnish>(); } public void AddBurger(Burger burger) { _burgers.Add(burger); } public void AddPizza(Pizza pizza) { _pizzas.Add(pizza); } public void AddGarnish(Garnish garnish) { _garnish.Add(garnish); } public void AddToppings(Topping topping) { _topping.Add(topping); } } }
问题根源
LoadToppings和LoadGarnishes方法仅提取了第一个<>包裹的条目,未循环处理所有配料/装饰LoadPizzas和LoadBurgers中提取配料列表时,仅获取了整个字符串,未拆分为单个配料名称- 调用Load方法时,仅添加了单个对象,未处理批量添加逻辑
修复方案
1. 修改Load方法为批量返回列表
将LoadToppings改为返回List<Topping>,LoadGarnishes改为返回List<Garnish>,循环解析所有条目:
static List<Topping> LoadToppings(string toppingsLine) { var toppings = new List<Topping>(); // 提取[]内的内容 int start = toppingsLine.IndexOf('[') + 1; int end = toppingsLine.IndexOf(']'); string toppingsContent = toppingsLine.Substring(start, end - start); // 拆分每个<name,price>条目 string[] toppingEntries = toppingsContent.Split(new[] { ">,<" }, StringSplitOptions.RemoveEmptyEntries); foreach (string entry in toppingEntries) { // 清理首尾的<> string cleanedEntry = entry.Trim('<', '>'); string[] parts = cleanedEntry.Split(','); if (parts.Length == 2) { string name = parts[0].Trim(); string price = parts[1].Trim(); toppings.Add(new Topping(name, price)); } } return toppings; } static List<Garnish> LoadGarnishes(string garnishesLine) { var garnishes = new List<Garnish>(); int start = garnishesLine.IndexOf('[') + 1; int end = garnishesLine.IndexOf(']'); string garnishesContent = garnishesLine.Substring(start, end - start); string[] garnishEntries = garnishesContent.Split(new[] { ">,<" }, StringSplitOptions.RemoveEmptyEntries); foreach (string entry in garnishEntries) { string cleanedEntry = entry.Trim('<', '>'); if (!string.IsNullOrEmpty(cleanedEntry)) { string[] parts = cleanedEntry.Split(','); if (parts.Length == 2) { string name = parts[0].Trim(); string price = parts[1].Trim(); garnishes.Add(new Garnish(name, price)); } } } return garnishes; }
2. 修改Pizza和Burger的Load方法,拆分配料列表
调整LoadPizzas和LoadBurgers,将配料字符串拆分为单个名称:
static Pizza LoadPizzas(string pizzaLine) { // 提取<>内的内容 int start = pizzaLine.IndexOf('<') + 1; int end = pizzaLine.IndexOf('>'); string pizzaContent = pizzaLine.Substring(start, end - start); // 拆分Name、Toppings、Price string[] pizzaParts = pizzaContent.Split(new[] { ",Toppings:", ",Price:" }, StringSplitOptions.None); string name = pizzaParts[0].Replace("Name:", "").Trim(); string toppingsStr = pizzaParts[1].Trim('[', ']'); string price = pizzaParts[2].Trim(); // 拆分配料名称 List<string> toppingNames = string.IsNullOrEmpty(toppingsStr) ? new List<string>() : toppingsStr.Split(',').Select(t => t.Trim()).ToList(); return new Pizza(name, toppingNames, price); } static Burger LoadBurgers(string burgerLine) { int start = burgerLine.IndexOf('<') + 1; int end = burgerLine.IndexOf('>'); string burgerContent = burgerLine.Substring(start, end - start); string[] burgerParts = burgerContent.Split(new[] { ",Garnishes:", ",Price:" }, StringSplitOptions.None); string name = burgerParts[0].Replace("Name:", "").Trim(); string garnishesStr = burgerParts[1].Trim('[', ']'); string price = burgerParts[2].Trim(); List<string> garnishNames = string.IsNullOrEmpty(garnishesStr) ? new List<string>() : garnishesStr.Split(',').Select(g => g.Trim()).ToList(); return new Burger(name, garnishNames, price); }
注:这里假设
Pizza和Burger类的构造函数支持接收List<string>类型的配料参数,如果原构造函数是接收字符串,需要同步修改类定义。
3. 修改调用逻辑,批量添加对象
在switch语句中,循环添加批量返回的对象:
switch (token) { case "Toppings": List<Topping> toppings = LoadToppings(file); foreach (var topping in toppings) { menu.AddToppings(topping); } break; case "Garnishes": List<Garnish> garnishes = LoadGarnishes(file); foreach (var garnish in garnishes) { menu.AddGarnish(garnish); } break; case "Pizza": Pizza pizza = LoadPizzas(file); menu.AddPizza(pizza); break; case "Burger": Burger burger = LoadBurgers(file); menu.AddBurger(burger); break; }
额外注意事项
- 确保
Topping、Garnish、Pizza、Burger类的构造函数参数与修改后的Load方法返回值匹配 - 可以添加异常处理逻辑,防止文本格式异常导致解析失败
内容的提问来源于stack exchange,提问作者Legois
相关产品推荐
相关产品推荐

