⽬录
【诞⽣背景】
【Convert YAML and Properties File 插件的不⾜】【⾃写⼩⼯具 YmlUtils 实现】【源码展⽰】
【诞⽣背景】
最近在做某配置中⼼的时候,配置中⼼采⽤properties格式进⾏配置的(如下图)。
⽽我们⼯程的项⽬配置⽂件是yml格式的(如下图)。
如果⼈为⼿动的⼀条⼀条,将yml⽂件中的配置数据,添加到配置中⼼,难免会消耗⼤量的⼈⼒和精⼒,况且还容易输⼊错误。因此,需要⼀个⼯具或插件,将 yml ⽂件的格式,转换为properties⽂件。
【Convert YAML and Properties File 插件的不⾜】
IDEA 有⼀个插件叫 Convert YAML and Properties File, 于是,⾸先⽤了⼀下 这个插件后,发现了,发现这个插件不太友好,具体有以下⼏点。
⽐如,现在我们有如下的 yml 配置⽂件:
我们⽤插件将它转化为 properties ⽂件。
下⾯是转化后的效果:
从这转换后的效果,我们不难发现该插件有以下⼏点问题:
(1)转化后,原 yml 配置⽂件消失(如果转出了问题,想看原配置⽂件,还看不了了);
(2)排序出现混乱,没有按照原 yml ⽂件数据进⾏输出(msg相关的配置本来在原yml⽂件中是第⼆个配置,转换后却成为了第⼀个;同理,mybatis的配置本是最后⼀个,转化后却放在了第⼆个);
(3)所有注释均不见了(所有相关的注释全都不见了,包括⾏级注释和末尾注释);(4)某些值没有进⾏配置,但转化后,却显⽰为了 null 字符串(如 msg.sex 的配置);(5)该插件仅IDEA有,Eclipse中还没有,不能垮开发⼯具使⽤;
【⾃写⼩⼯具 YmlUtils 实现】
针对上⾯ IDEA 插件的不⾜,于是⾃⼰写了⼀款⼩⼯具 YmlUtils(源码在⽂章结尾处 ),你可以将它放在⼯程中的任何位置。
现在,我们同样以刚刚的 yml 配置⽂件为测试模板,来测试下这款⼩⼯具。
测试的⽅法很简单,只需要将 yml 配置⽂件放在根⽬录下,然后写个 Test 类,调⽤⾥⾯的 castProperties ⽅法即可。
YmlUtils.castProperties(\"application-test.yml\");
执⾏⽅法后,⾸先我们可以看到控制台会将 porperties ⽂件的内容打印到控制台上⾯:
程序运⾏完成后,根⽬录下会多出⼀个与yml同名的properties⽂件,该⽂件就直接拷贝到相应的地⽅进⾏使⽤,⽽且原⽂件也并未收到任何损坏和影响。
【源码展⽰】
最后附上⼯具类源码,如果对你有⽤,记得⼀键三连(⽀持原创)。
package com.test.utils;
import java.io.File;
import java.io.FileInputStream;import java.io.FileWriter;import java.io.IOException;
import java.nio.charset.StandardCharsets;import java.util.*; /**
* Yaml 配置⽂件转 Properties 配置⽂件⼯具类 * @author https://zyqok.blog.csdn.net/ * @since 2021/08/24 */
public class YmlUtils {
/**
* 将 yml ⽂件转化为 properties ⽂件 *
* @param ymlFileName ⼯程根⽬录下(⾮resources⽬录)的 yml ⽂件名称(如:abc.yml) * @return List public static List if (ymlFileName == null || ymlFileName.isEmpty() || !ymlFileName.endsWith(\".yml\")) { throw new RuntimeException(\"请输⼊yml⽂件名称!!\"); } File ymlFile = new File(ymlFileName); if (!ymlFile.exists()) { throw new RuntimeException(\"⼯程根⽬录下不存在 \" + ymlFileName + \"⽂件!!\"); } String fileName = ymlFileName.split(\".yml\ // 获取⽂件数据 String yml = read(ymlFile); List String str = printNodeList(nodeList); // 将数据写⼊到 properties ⽂件中 String propertiesName = fileName + \".properties\"; File file = new File(propertiesName); if (!file.exists()) { try { file.createNewFile(); } catch (IOException e) { e.printStackTrace(); } } try (FileWriter writer = new FileWriter(file)) { writer.write(str); writer.flush(); } catch (IOException e) { e.printStackTrace(); } return nodeList; } /** * 将yml转化为porperties⽂件,并获取转化后的键值对 * * @param ymlFileName ⼯程根⽬录下的 yml ⽂件名称 * @return 转化后的 porperties ⽂件键值对Map */ public static Map List if (node.getKey().length() > 0) { map.put(node.getKey(), node.getValue()); } } return map; } private static String read(File file) { if (Objects.isNull(file) || !file.exists()) { return \"\"; } try (FileInputStream fis = new FileInputStream(file)) { byte[] b = new byte[(int) file.length()]; fis.read(b); return new String(b, StandardCharsets.UTF_8); } catch (IOException e) { e.printStackTrace(); } return \"\"; } private static String printNodeList(List if (node.getLast().equals(Boolean.FALSE)) { continue; } if (node.getEmptyLine().equals(Boolean.TRUE)) { System.out.println(); sb.append(\"\\r\\n\"); continue; } // 判断是否有⾏级注释 if (node.getHeadRemark().length() > 0) { String s = \"# \" + node.getHeadRemark(); System.out.println(s); sb.append(s).append(\"\\r\\n\"); continue; } // 判断是否有⾏末注释 (properties中注释不允许末尾注释,故⽽放在上⾯) if (node.getTailRemark().length() > 0) { String s = \"# \" + node.getTailRemark(); System.out.println(s); sb.append(s).append(\"\\r\\n\"); } // String kv = node.getKey() + \"=\" + node.getValue(); System.out.println(kv); sb.append(kv).append(\"\\r\\n\"); } return sb.toString(); } private static List List Map YmlNode node = getNode(line); if (node.getKey() != null && node.getKey().length() > 0) { int level = node.getLevel(); if (level == 0) { keyMap.clear(); keyMap.put(0, node.getKey()); } else { int parentLevel = level - 1; String parentKey = keyMap.get(parentLevel); String currentKey = parentKey + \".\" + node.getKey(); keyMap.put(level, currentKey); node.setKey(currentKey); } } keySet.add(node.getKey() + \".\"); nodeList.add(node); } // 标识是否最后⼀级 for (YmlNode each : nodeList) { each.setLast(getNodeLast(each.getKey(), keySet)); } return nodeList; } private static boolean getNodeLast(String key, Set key = key + \".\"; int count = 0; for (String each : keySet) { if (each.startsWith(key)) { count++; } } return count == 1; } private static YmlNode getNode(String line) { YmlNode node = new YmlNode(); // 初始化默认数据(防⽌NPE) node.setEffective(Boolean.FALSE); node.setEmptyLine(Boolean.FALSE); node.setHeadRemark(\"\"); node.setKey(\"\"); node.setValue(\"\"); node.setTailRemark(\"\"); node.setLast(Boolean.FALSE); node.setLevel(0); // 空⾏,不处理 String trimStr = line.trim(); if (trimStr.isEmpty()) { node.setEmptyLine(Boolean.TRUE); return node; } // ⾏注释,不处理 if (trimStr.startsWith(\"#\")) { node.setHeadRemark(trimStr.replaceFirst(\"#\ return node; } // 处理值 String[] strs = line.split(\":\ // 拆分后长度为0的,属于异常数据,不做处理 if (strs.length == 0) { return node; } // 获取键 node.setKey(strs[0].trim()); // 获取值 String value; if (strs.length == 2) { value = strs[1]; } else { value = \"\"; } // 获取⾏末备注 String tailRemark = \"\"; if (value.contains(\" #\")) { String[] vs = value.split(\"#\ if (vs.length == 2) { value = vs[0]; tailRemark = vs[1]; } } node.setTailRemark(tailRemark.trim()); node.setValue(value.trim()); // 获取当前层级 int level = getNodeLevel(line); node.setLevel(level); node.setEffective(Boolean.TRUE); return node; } private static int getNodeLevel(String line) { if (line.trim().isEmpty()) { return 0; } char[] chars = line.toCharArray(); int count = 0; for (char c : chars) { if (c != ' ') { break; } count++; } return count / 2; }} class YmlNode { /** 层级关系 */ private Integer level; /** 键 */ private String key; /** 值 */ private String value; /** 是否为空⾏ */ private Boolean emptyLine; /** 当前⾏是否为有效配置 */ private Boolean effective; /** 头部注释(单⾏注释) */ private String headRemark; /** 末尾注释 */ private String tailRemark; /** 是否为最后⼀层配置 */ private Boolean last; public Boolean getLast() { return last; } public void setLast(Boolean last) { this.last = last; } public Integer getLevel() { return level; } public void setLevel(Integer level) { this.level = level; } public String getKey() { return key; } public void setKey(String key) { this.key = key; } public String getValue() { return value; } public void setValue(String value) { this.value = value; } public Boolean getEmptyLine() { return emptyLine; } public void setEmptyLine(Boolean emptyLine) { this.emptyLine = emptyLine; } public Boolean getEffective() { return effective; } public void setEffective(Boolean effective) { this.effective = effective; } public String getHeadRemark() { return headRemark; } public void setHeadRemark(String headRemark) { this.headRemark = headRemark; } public String getTailRemark() { return tailRemark; } public void setTailRemark(String tailRemark) { this.tailRemark = tailRemark; } } 到此这篇关于Yml转properties⽂件⼯具类YmlUtils(不⽤引任何插件和依赖)的⽂章就介绍到这了,更多相关Yml转properties⽂件⼯具类YmlUtils内容请搜索以前的⽂章或继续浏览下⾯的相关⽂章希望⼤家以后多多⽀持! 因篇幅问题不能全部显示,请点此查看更多更全内容