yaml文件差异化比较

背景

多迭代、多环境部署项目时,nacos升级时不知道哪些配置文件修改了。

效果

老的配置文件:

新的配置文件:

 

文件夹级别:t2是完全一样的,删除了t5,新增了t6、t7 

 内容级别:

t1:

++rsa:
  private-key: |
    XXXXXXXXXXXXXX
  public-key: |
    QQQQQQQQQQQQQQ
++xss:
  enabled: true
  ignoreUrls:
    - /XXX/XX
    - /TTT/XX/XX
  validReferer:
    - http://localhost
    - http://192.22.81.34
---
--mail:
  smtp:
    host: XX.XXX.XX.XX
    password: 123456
    port: ''
    sender:
      address: XX
      alias: XX
    ssl:
      port: 25
    user: XX.com
---
spring:
  datasource:
    url: jdbc:mysql://XX.XXX.XX.XX:XX/${database.name:TEST}?useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&transformedBitIsBoolean=true&allowMultiQueries=true&useSSL=false
      => jdbc:mysql://XX.XXX.XX.XX:XX/${database.name:DEV}?useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&transformedBitIsBoolean=true&allowMultiQueries=true&useSSL=false&autoReconnect=true&failOverReadOnly=false

实现

添加maven依赖:

        <dependency>
            <groupId>org.yaml</groupId>
            <artifactId>snakeyaml</artifactId>
            <version>2.0</version>
        </dependency>

代码:

package org.example;

import lombok.Data;
import org.junit.jupiter.api.Test;
import org.yaml.snakeyaml.DumperOptions;
import org.yaml.snakeyaml.Yaml;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.nio.channels.FileChannel;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * Unit test for simple App.
 */
public class AppTest {


    private String ADD_TAG = "++";
    private String DELETE_TAG = "--";
    private String UPDATE_TAG = " => ";


    private String OLD_PATH = "D:/yaml-test/old";
    private String NEW_PATH = "D:/yaml-test/new";

    private String OUT_PATH = "D:/yaml-test/update";

    @Test
    public void test() throws IOException {
        tt(OLD_PATH, NEW_PATH);
    }

    /**
     * @description 非核心逻辑
     * @author gang.tu
     */
    public void tt(String oldPath, String newPath) throws IOException {
        Yaml yaml = getYaml();
        File[] oldFile = new File(oldPath).listFiles();
        File[] newFile = new File(newPath).listFiles();
        if (!new File(OUT_PATH).exists()) {
            new File(OUT_PATH).mkdirs();
        }
        for (File nFile : newFile) {
            String updateFilePath = OUT_PATH + File.separator + nFile.getName();
            boolean find = false;
            for (File oFile : oldFile) {
                if (nFile.getName().equals(oFile.getName())) {
                    find = true;
                    List<Map<String, Object>> diffList = diff(oFile, nFile, yaml);
                    if (!diffList.isEmpty()) {
                        yaml.dumpAll(diffList.iterator(), new FileWriter(updateFilePath));
                    }
                    continue;
                }
            }
            if (!find) {
                FileChannel sourceChannel = null;
                FileChannel destChannel = null;
                try {
                    sourceChannel = new FileInputStream(nFile).getChannel();
                    destChannel = new FileOutputStream(updateFilePath + "--新增配置文件").getChannel();
                    destChannel.transferFrom(sourceChannel, 0, sourceChannel.size());
                } finally {
                    sourceChannel.close();
                    destChannel.close();
                }
            }
        }

        for (File oFile : oldFile) {
            String updateFilePath = OUT_PATH + File.separator + oFile.getName();
            boolean find = false;
            for (File nFile : newFile) {
                if (nFile.getName().equals(oFile.getName())) {
                    find = true;
                    continue;
                }
            }
            if (!find) {
                FileChannel sourceChannel = null;
                FileChannel destChannel = null;
                try {
                    sourceChannel = new FileInputStream(oFile).getChannel();
                    destChannel = new FileOutputStream(updateFilePath + "--删除配置文件").getChannel();
                    destChannel.transferFrom(sourceChannel, 0, sourceChannel.size());
                } finally {
                    sourceChannel.close();
                    destChannel.close();
                }
            }
        }
    }

    /**
     * @description 核心逻辑
     * @author gang.tu
     */
    public List<Map<String, Object>> diff(File oldFile, File newFile, Yaml yaml) throws FileNotFoundException {
        Map<String, Object> oldMap = yaml.load(new FileInputStream(oldFile));
        Map<String, Object> newMap = yaml.load(new FileInputStream(newFile));
        List<Map<String, Object>> all = new ArrayList<>();
        Map<String, Object> updateMap = new LinkedHashMap<>();
        all.add(getAdd(oldMap, newMap));
        all.add(getDelete(oldMap, newMap));
        deal(oldMap, newMap, null, updateMap);
        all.add(updateMap);
        all = all.stream().filter(e -> !e.isEmpty()).collect(Collectors.toList());
        return all;
    }


    private Yaml getYaml() {
        DumperOptions options = new DumperOptions();
        options.setIndentWithIndicator(true);
        options.setIndicatorIndent(2);
        options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
        return new Yaml(options);
    }


    private void deal(Map<String, Object> oldMap, Map<String, Object> newMap, String parentKey, Map<String, Object> resultMap) {
        Set<String> update = getUpdateKeys(oldMap.keySet(), newMap.keySet());
        Map<String, Object> updateMap;
        if (parentKey == null) {
            extracted(oldMap, newMap, update, resultMap);
        } else {
            updateMap = (Map<String, Object>) resultMap.get(parentKey);
            extracted(oldMap, newMap, update, updateMap);
        }
    }

    private void extracted(Map<String, Object> oldMap, Map<String, Object> newMap, Set<String> update, Map<String, Object> updateMap) {
        for (String key : update) {
            Object oldValue = oldMap.get(key);
            Object newValue = newMap.get(key);
            if (Objects.equals(oldValue, newValue)) {
                continue;
            }
            if (oldValue.getClass() == newValue.getClass()) {
                if (newValue instanceof Map) {
                    updateMap.put(key, new LinkedHashMap<>());
                    deal((Map<String, Object>) oldValue, (Map<String, Object>) newValue, key, updateMap);
                    if (((Map<String, Object>) updateMap.get(key)).isEmpty()) {
                        updateMap.remove(key);
                    }
                } else if (newValue instanceof List) {
                    if (!Objects.equals(oldValue, newValue)) {
                        updateMap.put(DELETE_TAG + key, oldValue);
                        updateMap.put(ADD_TAG + key, newValue);
                    }
                } else {
                    if (!Objects.equals(oldValue, newValue)) {
                        updateMap.put(key, oldValue + UPDATE_TAG + newValue);
                    }
                }
            } else {
                updateMap.put(DELETE_TAG + key, oldValue);
                updateMap.put(ADD_TAG + key, newValue);
            }
        }
    }

    private void dd() {

    }

    private Map<String, Object> getDelete(Map<String, Object> oldMap, Map<String, Object> newMap) {
        Set<String> delete = getDeleteKeys(oldMap.keySet(), newMap.keySet());
        return getResultMap(delete, oldMap, DELETE_TAG);
    }

    private Map<String, Object> getAdd(Map<String, Object> oldMap, Map<String, Object> newMap) {
        Set<String> add = getAddKeys(oldMap.keySet(), newMap.keySet());
        return getResultMap(add, newMap, ADD_TAG);
    }

    private Map<String, Object> getResultMap(Set<String> keys, Map<String, Object> map, String tag) {
        Map<String, Object> res = new LinkedHashMap<>();
        for (String key : keys) {
            res.put(tag + key, map.get(key));
        }
        return res;
    }

    private void aaa(Map<String, Object> map1, int level, String parentKey) {
        MapNode mapNode = new MapNode();
        Set<String> keys = new HashSet<>();
        Set<String> strings = map1.keySet();
        Collection<Object> values = map1.values();

        for (Map.Entry<String, Object> entry : map1.entrySet()) {
            String key = entry.getKey();
            mapNode.setLevel(level);
            keys.add(key);
            Object value = entry.getValue();
        }
    }

    @Data
    static class MapNode<K, V> {
        private int level;
        private String parentKey;
        private Set<String> keys;
        Collection<Object> values;
    }


    private Set<String> getAddKeys(Set<String> source, Set<String> target) {
        if (source == null) {
            return target;
        }
        Set<String> t = new HashSet<>(target);
        t.removeAll(source);
        return t;
    }

    private Set<String> getDeleteKeys(Set<String> source, Set<String> target) {
        if (target == null) {
            return source;
        }
        Set<String> s = new HashSet<>(source);
        s.removeAll(target);
        return s;
    }

    private Set<String> getUpdateKeys(Set<String> source, Set<String> target) {
        if (source == null) {
            return target;
        }
        Set<String> t = new HashSet<>(target);
        t.retainAll(source);
        return t;
    }

}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 相机内参文件是一种记录相机的内部参数的文件格式。相机的内部参数是指描述相机光学特性和成像特性的一组参数,通常包括焦距、主点、径向畸变系数等。 常见的相机内参文件格式有XML格式、YAML格式和JSON格式等。这些文件格式都是用来存储相机内参数的,并以文本形式保存,用户可以通过读取这些文件来获取相机的内部参数信息。 在这些文件中,通常包含了相机的品牌、型号、分辨率等基本信息,以及具体的内部参数值。相机内参文件还可以包含一些其他的信息,比如标定板的尺寸、畸变矫正模型等。 相机内参文件的格式一般采用名值对的形式,通过一系列的参数键值对来描述内部参数。例如,在XML格式中,使用标签来表示参数的名称,然后将参数的值嵌套在标签内部;在YAML和JSON格式中,使用键值对的形式来表示参数名和参数值。 使用相机内参文件可以方便地进行相机标定,将相机的内部参数导入到计算机视觉等应用中,对图像进行处理和分析。无论是机器人视觉、三维重建还是虚拟现实等领域,相机内参文件都是必不可少的工具。 总之,相机内参文件是记录相机内部参数的一种文件格式,可以方便地保存和传输相机的内部参数信息,为各种图像处理和分析应用提供基础数据。 ### 回答2: 相机内参文件是一种包含相机的内部参数的文件,用于校正相机图像。相机内参是指相机的光学特性和成像过程的相关参数,包括焦距、主点位置、畸变等。相机内参文件格式一般是以文本形式保存,常见的格式有XML、YAML和JSON等。 XML格式是一种标记语言,用于描述具有层次结构的数据,相机内参以元素和属性的形式存储。例如,可以使用标签<Camera>表示一个相机对象,其中包含<Intrinsic>和<Distortion>标签,分别描述相机的内参和畸变参数。 YAML格式是一种易于阅读和编写的数据序列化格式,相机内参以键值对的形式存储。例如,可以使用键值对"Camera"表示一个相机对象,其中包含键"Intrinsic"和"Distortion",对应相机的内参和畸变参数。 JSON格式是一种轻量级的数据交换格式,相机内参以键值对的方式存储。例如,可以使用键值对"camera"表示一个相机对象,其中包含键"intrinsic"和"distortion",对应相机的内参和畸变参数。 无论是哪种格式,相机内参文件都将相机的内部参数信息保存下来,供后续的图像处理和校正使用。使用这些内参文件,可以矫正图像中的畸变,提高图像的质量和准确性。这对于计算机视觉和机器人等领域的应用非常重要。 ### 回答3: 相机内参是指描述相机镜头特性的参数,用于校正图像畸变和计算图像的三维结构。常见的相机内参文件格式一般是XML或YAML格式。 XML格式:XML是一种标记语言,可用于存储和传输数据。在相机内参文件中,XML格式可以将相机参数以标签的形式进行包装,每个标签表示一个参数,例如焦距、主点坐标、畸变系数等。将这些参数以标签形式存储在XML文件中,可以清晰地表示相机内参信息。 YAML格式:YAML是一种易读的数据序列化格式,它可以表示多种数据类型,如数组、字典和字符串等。在相机内参文件中,YAML格式可以将相机参数以键值对的形式进行存储,每个键表示一个参数,对应的值表示该参数的具体数值。通过使用YAML格式,可以简洁地存储相机内参信息。 相机内参文件的格式不仅在存储上有所差异,还体现了不同的软件和库对相机内参的处理方式。例如,OpenCV库通常使用XML格式来存储和读取相机内参,而ROS(机器人操作系统)则主要使用YAML格式。 总之,相机内参文件格式可以通过XML或YAML等格式来表示,这些格式都可以清晰地存储相机参数,并为后续处理提供方便。在选择格式时,可以根据具体的应用场景和对文件读写的要求来决定使用哪种格式。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值