• 撸码是需要直觉的


    随着撸码的时间增加,码感也会加强,今天看一个编码直觉案例吧!

     

    案例:

    需求:把查询到的数据列表生成csv文件

    nuget包:CsvHelper

     

    数据实体类:

        /// <summary>
        /// 商品
        /// </summary>
        public class Goods
        {
            /// <summary>
            /// 编号
            /// </summary>
            public uint ID
            { get; set; }
            /// <summary>
            /// 名称
            /// </summary>
            public string Name
            { get; set; }
            /// <summary>
            /// 规格
            /// </summary>
            public string Spec
            { get; set; }
            /// <summary>
            /// 单位
            /// </summary>
            public string Unit
            { get; set; }
            /// <summary>
            /// 制造商
            /// </summary>
            public string Manufacturer
            { get; set; }
            /// <summary>
            /// 价格
            /// </summary>
            public decimal Price
            { get; set; }
            /// <summary>
            /// 这里是为了打印数据方例重写ToString()
            /// </summary>
            public override string ToString()
            {
                return $"ID={ID},Name={Name},Unit={Unit},Spec={Spec},Price={Price},Manufacturer={Manufacturer}";
            }
        }

    定义了一个csv操作的接口:

    public interface ICsvHandle
    {
        List<Goods> ReadCsv(string file);
        void WriteCsv(string file, List<Goods> goodses);
    }

      为了演示方便,Demo中的数据列表是通过Bogus产生(bogus在之前的文章中介绍过)

      static List<Goods> GoodsCreater()
            {
                var goodses = new List<Goods>();
                var options = new JsonSerializerOptions();
                options.Encoder = System.Text.Encodings.Web.JavaScriptEncoder.Create(UnicodeRanges.All);
                for (var i = 0; i < 100; i++)
                {
                    var goodsFaker = new Faker<Goods>("zh_CN")
                        .RuleFor(x => x.ID, x => x.Random.UInt())
                        .RuleFor(x => x.Name, x => x.Random.ArrayElement(
                            new string[]
                            {
     "甲销唑注射液",
    "葡萄糖注射液",
    "盐水(氯化钠)",
    "利巴韦林病毒唑针",
    "氟康唑氯化钠注射液(康锐)",
    "安痛定针",
    "维生素B12针",
    "硫酸阿米卡星注射液",
    "氯化钠注射液(塑料瓶)",
    "转移因子注射液",
    "血塞通粉针",
    "苦碟子注射液",
    "注射用培美曲塞二钠(爱立汀)",
    "左克注射液",
    "维生素C注射液",
    "硫酸庆大霉素注射液",
    "盐酸左氧氟沙星注射液",
    "蔗糖铁注射液",
    "注射用青霉素钠",
    "维生素B1针",
    "疏血通注射液",
    "胃复安盐酸甲氧氯普胺注射液",
    "硫酸庆大霉素注射液",
    "葡萄糖注射液50%",
    "银杏达莫注射液",
    "硫酸庆大霉素注射液",
    "5%葡萄糖注射液",
    "注射用氨曲南",
                            }
                            ))
                        .RuleFor(x => x.Price, x => x.Random.Decimal())
                        .RuleFor(x => x.Unit, x => x.Random.ArrayElement(new string[] { "", "", "", "", "", "" }))
                        .RuleFor(x => x.Spec, x => x.Random.ArrayElement(new string[]
                           {
     "5*20ml",
    "250ml",
    "1ml*10支",
    "100ml:0.2g",
    "2毫升*10支",
    "10支",
    "2ml*10.2克*10支",
    "100ml",
    "3毫升:2毫升*10支",
    "20毫克",
    "10mg*10支",
    "0.5克",
    "2ml:0.1g",
    "0.25G*2ML",
    "4万单位*10支",
    "100ml*0.1g",
    "1g",
    "80万单位",
    "2ml*10支",
    "5毫克*60片",
    "1ml:10mg",
    "4万*2ml*10支",
    "20ML*5支",
    "5ml",
    "2ml:40mg(4万单位)",
    "250ml",
    "0.5克*10支",
    "5ML;17.5MG",
    "2ML:0.5G*10支",
                           }))
                        .RuleFor(x => x.Manufacturer, x => x.Random.ArrayElement(
                            new string[]
                        {
     "山东齐都药业/山西云鹏",
    "侯马霸王药业/山西晋新双鹤/天津新郑/西安/贵州",
    "山西临汾云鹏药业、山东齐都药业/山西银湖/石家庄四药/河南科伦",
    "安徽联谊/无锡",
    "扬子江药业集团",
    "新乡常乐制药/山西太原药业/天津焦作/郑州",
    "天津药业焦作",
    "山东方明药业集团股份有限公司",
    "石家庄四药有限公司",
    "湖南一格制药有限公司",
    "哈尔滨",
    "通化华夏制药有限责任公司",
    "德州德药制药有限公司",
    "扬子江药业",
    "山西晋新双鹤药业/新乡市新辉药业/河南润弘",
    "河南辅仁怀庆堂制药/濮阳市汇元药业/新乡常乐",
    "广西裕源药业、四川科伦大药厂",
    "成都天台山制药有限公司",
    "华北制药",
    "安阳九州药业、山东方明药业/石药银湖制药",
    "牡丹江友博药业有限公司",
    "濮阳汇元/天津药业集团新郑",
    "天津药业焦作/侯马",
    "湖南科伦/焦作民康",
    "贵州益佰制药股份有限公司",
    "新乡市新辉药业/新乡常乐制药/濮阳市汇元药业",
    "山东华鲁制药/山东齐都/山西云鹏制药/西安汉丰",
    "重庆圣华曦药业",
                        }));
                    goodses.Add(goodsFaker.Generate());
                }
                return goodses;
            }

    第一版:

    csv文件格式是utf8

    public class BasisCsvHandle : 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))
            {
                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);
                }
            }
        }
    }

      后来有的客户要BOM类型的UTF8,其实就是在文件开头加上byte[] BOM = { 0xEF, 0xBB, 0xBF };这个字节数组就ok

      为了适配合有无BOM和非BOM的UTF8,对接口进行了重构,增加默认属性(正好练一下接口默认属性的用法),这种做法的好处是不打扰BasisCsvHandle的代码,当然,也可以更深层的重构ICsvHandle中的两个方法来适配是否是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)
            {
                //追究加BOM
                using (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);
                }
            }
        }
    }

      虽然能实现功能,但是觉得这样的代码太啰嗦,这里的本质就是在写数据时加上三个字节,读取数据时,少读三个字节直觉告诉我,应该好像也许或者能有更简单的方式。

    第三版:

    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);
                }
            }
        }
    }
      想要更快更方便的了解相关知识,可以关注微信公众号 
     

     

  • 相关阅读:
    (IEEE-754) 字节数组与浮点数之间的互相转换(MODBUS float类型)
    C#中浮点数依IEEE-754标准转二进制串 (MODBUS 浮点数转换)
    SQL 向上取整、向下取整、四舍五入取整的实例!round、rounddown、roundup
    查看SQL SERVER数据库运行参数和连接数
    three.js 材质
    three.js 曲线
    three.js 几何体-组合网格
    three.js 几何体(三)
    three.js 几何体(二)
    three.js 几何体(一)
  • 原文地址:https://www.cnblogs.com/axzxs2001/p/15863060.html
Copyright © 2020-2023  润新知