C# 读写解析yml文件快速修改,快速保存

由于项目涉及到使用c#来修改java的配置文件,java项目使用的是spring boot开发,配置文件使用的是yaml格式,所以要使用c#来读取和设置yml文件,在百度找了好久发现这方面的资料还是相对少的。

后来发现了个c#的库叫YamlDotNet,但查看官方的Samples后,发现并没有个合适的对yml进行简单快速操作的。

于是想干脆动手写个解析工具类,花了大概半天的时间完成了这个简单工具类,目前可以支持多级配置,快速设置。代码一共才二百多行,欢迎大家使用和反馈

废话不多说,开始贴代码,注释写了很多,方便大家阅读

class YML
    {
        // 所有行
        private String[] lines;
        // 格式化为节点
        private List<Node> nodeList = new List<Node>();
        // 文件所在地址
        private String path;

        public YML(String path) {
            this.path = path;
            this.lines = File.ReadAllLines(path);

            for (int i = 0;i< lines.Length;i++) {
                String line = lines[i];
                if (line.Trim() == "")
                {
                    Console.WriteLine("空白行,行号:" + (i + 1));
                    continue;
                }
                else if(line.Trim().Substring(0,1) == "#"){
                    Console.WriteLine("注释行,行号:" + (i + 1));
                    continue;
                }

                String[] kv = Regex.Split(line,":", RegexOptions.IgnoreCase);
                findPreSpace(line);
                Node node = new Node();
                node.space = findPreSpace(line);
                node.name = kv[0].Trim();

                // 去除前后空白符
                String fline = line.Trim();
                int first = fline.IndexOf(':');
                node.value = first == fline.Length - 1 ? null : fline.Substring(first+2, fline.Length-first-2);
                node.parent = findParent(node.space);
                nodeList.Add(node);
            }

            this.formatting();
        }

        // 修改值 允许key为多级 例如:spring.datasource.url
        public void modify(String key,String value) {
            Node node = findNodeByKey(key);
            if (node != null) {
                node.value = value;
            }
        }

        // 读取值
        public String read(String key, String value) {
            Node node = findNodeByKey(key);
            if (node != null)
            {
                return node.value;
            }
            return null;
        }

        // 根据key找节点
        private Node findNodeByKey(String key) {
            String[] ks = key.Split('.');
            for (int i = 0; i < nodeList.Count; i++)
            {
                Node node = nodeList[i];
                if (node.name == ks[ks.Length - 1])
                {
                    // 判断父级
                    Node tem = node;
                    // 统计匹配到的次数
                    int count = 1;
                    for (int j = ks.Length - 2; j >= 0; j--)
                    {
                        if (tem.parent.name == ks[j])
                        {
                            count++;
                            // 继续检查父级
                            tem = tem.parent;
                        }
                    }

                    if (count == ks.Length)
                    {
                        return node;
                    }
                }
            }
            return null;
        }

        // 保存到文件中
        public void save() {
            StreamWriter stream = File.CreateText(this.path);
            for (int i = 0;i< nodeList.Count;i++) {
                Node node = nodeList[i];
                StringBuilder sb = new StringBuilder();
                // 放入前置空格
                for (int j = 0;j < node.tier;j++) {
                    sb.Append("  ");
                }
                sb.Append(node.name);
                sb.Append(": ");
                if (node.value != null) {
                    sb.Append(node.value);
                }
                stream.WriteLine(sb.ToString());
            }
            stream.Flush();
            stream.Close();
        }

        // 格式化
        public void formatting() {
            // 先找出根节点
            List<Node> parentNode = new List<Node>();
            for (int i = 0;i < nodeList.Count;i++) {
                Node node = nodeList[i];
                if (node.parent == null) {
                    parentNode.Add(node);
                }
            }

            List<Node> fNodeList = new List<Node>();
            // 遍历根节点
            for (int i = 0; i < parentNode.Count; i++)
            {
                Node node = parentNode[i];
                fNodeList.Add(node);
                findChildren(node, fNodeList);
            }

            Console.WriteLine("完成");

            // 指针指向格式化后的
            nodeList = fNodeList;
        }


        // 层级
        int tier = 0;
        // 查找孩子并进行分层
        private void findChildren(Node node,List<Node> fNodeList) {
            // 当前层 默认第一级,根在外层进行操作
            tier++;
            
            for (int i = 0; i < nodeList.Count; i++)
            {
                Node item = nodeList[i];
                if (item.parent == node) {
                    item.tier = tier;
                    fNodeList.Add(item);
                    findChildren(item,fNodeList);
                }
            }

            // 走出一层
            tier--;
        }

        //查找前缀空格数量
        private int findPreSpace(String str) {
            List<char> chars = str.ToList();
            int count = 0;
            foreach (char c in chars) {
                if (c == ' ')
                {
                    count++;
                }
                else {
                    break;
                }
            }
            return count;
        }

        // 根据缩进找上级
        private Node findParent(int space) {
            
            if (nodeList.Count == 0)
            {
                return null;
            }
            else {
                // 倒着找上级
                for (int i = nodeList.Count -1;i >= 0;i--) {
                    Node node = nodeList[i];
                    if (node.space < space) {
                        return node;
                    }
                }
                // 如果没有找到 返回null
                return null;
            }
        }

        // 私有节点类
        private class Node {
            // 名称
            public String name { get; set; }
            // 值
            public String value { get; set; }
            // 父级
            public Node parent { get; set; }
            // 前缀空格
            public int space { get; set; }
            // 所属层级
            public int tier { get; set; }
        }
    }
使用的话也是很简单的
String filePath = Directory.GetCurrentDirectory() + @"\application.yml";
YML yml = new YML(filePath);
yml.modify("spring.datasource.url", "567890");
yml.save();
  • 12
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值