撸码是需要直觉的
隨著擼碼的時(shí)間增加,碼感也會(huì)加強(qiáng),今天看一個(gè)編碼直覺(jué)案例吧!
案例:
需求:把查詢到的數(shù)據(jù)列表生成csv文件
nuget包:CsvHelper
數(shù)據(jù)實(shí)體類:
/// <summary>/// 商品/// </summary>public class Goods{/// <summary>/// 編號(hào)/// </summary>public uint ID{ get; set; }/// <summary>/// 名稱/// </summary>public string Name{ get; set; }/// <summary>/// 規(guī)格/// </summary>public string Spec{ get; set; }/// <summary>/// 單位/// </summary>public string Unit{ get; set; }/// <summary>/// 制造商/// </summary>public string Manufacturer{ get; set; }/// <summary>/// 價(jià)格/// </summary>public decimal Price{ get; set; }/// <summary>///?這里是為了打印數(shù)據(jù)方例重寫ToString()/// </summary>public override string ToString(){return $"ID={ID},Name={Name},Unit={Unit},Spec={Spec},Price={Price},Manufacturer={Manufacturer}";}}定義了一個(gè)csv操作的接口:
為了演示方便,Demo中的數(shù)據(jù)列表是通過(guò)Bogus產(chǎn)生(bogus在之前的文章中介紹過(guò))
第一版:
csv文件格式是utf8
后來(lái)有的客戶要BOM類型的UTF8,其實(shí)就是在文件開(kāi)頭加上byte[] BOM = { 0xEF, 0xBB, 0xBF };這個(gè)字節(jié)數(shù)組就ok
為了適配合有無(wú)BOM和非BOM的UTF8,對(duì)接口進(jìn)行了重構(gòu),增加默認(rèn)屬性(正好練一下接口默認(rèn)屬性的用法),這種做法的好處是不打擾BasisCsvHandle的代碼,當(dāng)然,也可以更深層的重構(gòu)ICsvHandle中的兩個(gè)方法來(lái)適配是否是BOM UTF8
public interface ICsvHandle {List<Goods> ReadCsv(string file);void?WriteCsv(string?file,?List<Goods>?goodses);private static bool _isBOM;public bool IsBOM { get => _isBOM; set => _isBOM = value; } }第二版:
public class StrengthenCsvHandle : ICsvHandle {public List<Goods> ReadCsv(string file){MemoryStream memory = null;using (var reader = new FileStream(file, FileMode.OpenOrCreate, FileAccess.ReadWrite)){var bytes = new byte[reader.Length];reader.Read(bytes, 0, bytes.Length);if (((ICsvHandle)this).IsBOM){bytes = bytes.Skip(3).Take(bytes.Length - 3).ToArray();}memory = new MemoryStream(bytes);}var config = new CsvConfiguration(CultureInfo.InvariantCulture){NewLine = "\r\n"};using (var reader = new StreamReader(memory))using (var csv = new CsvReader(reader, config)){var goodses = csv.GetRecords<Goods>();return goodses.ToList();}}public void WriteCsv(string file, List<Goods> goodses){var config = new CsvConfiguration(CultureInfo.InvariantCulture){NewLine = "\r\n"};using (var writer = new StreamWriter(file)){using (var csv = new CsvWriter(writer, config)){csv.WriteRecords(goodses);}}if (((ICsvHandle)this).IsBOM){//追究加BOMusing (var writer = new FileStream(file, FileMode.OpenOrCreate, FileAccess.ReadWrite)){var bytes = new byte[writer.Length];writer.Read(bytes, 0, bytes.Length);byte[] BOM = { 0xEF, 0xBB, 0xBF };var list = new List<byte>();list.AddRange(BOM);list.AddRange(bytes);writer.Position = 0;writer.Write(list.ToArray(), 0, list.Count);}}} }雖然能實(shí)現(xiàn)功能,但是覺(jué)得這樣的代碼太啰嗦,這里的本質(zhì)就是在寫數(shù)據(jù)時(shí)加上三個(gè)字節(jié),讀取數(shù)據(jù)時(shí),少讀三個(gè)字節(jié),直覺(jué)告訴我,應(yīng)該好像也許或者能有更簡(jiǎn)單的方式。
第三版:
public class PerfectCsvHandle : ICsvHandle {public List<Goods> ReadCsv(string file){var config = new CsvConfiguration(CultureInfo.InvariantCulture){NewLine = "\r\n"};using (var reader = new StreamReader(file))using (var csv = new CsvReader(reader, config)){if (((ICsvHandle)this).IsBOM){reader.BaseStream.Position = 3;}var goodses = csv.GetRecords<Goods>();return goodses.ToList();}}public void WriteCsv(string file, List<Goods> goodses){var config = new CsvConfiguration(CultureInfo.InvariantCulture){NewLine = "\r\n"};using (var writer = new StreamWriter(file)){using (var csv = new CsvWriter(writer, config)){if (((ICsvHandle)this).IsBOM){byte[] BOM = { 0xEF, 0xBB, 0xBF };writer.Write(System.Text.Encoding.UTF8.GetString(BOM));}csv.WriteRecords(goodses);}}} }總結(jié)
- 上一篇: 记一次 .NET医疗布草API程序 内存
- 下一篇: Mongo规范