java 读写yml文件,修改文件内容保持原格式

我理解的yml文件

在我们学习过springboot项目的同学对这个文件肯定是特别熟悉,通常我们都是用它来修改保存我们的项目配置,最简单的就是数据库的配置,然后就是资源读取配置,redies配置,缓存配置,以及jwt的配置等等,因为yml文件主要用于我们的项目配置,所以一个特点就是易于人们阅读,修改;即使一个刚接触yml文件的人加上简单的注释,肯定也能够看懂打部分内容的;
我总结的特点就是:

  1. 直观,易于阅读,修改
  2. 可以把对象的层次结构展现得很直观
  3. 用key:value的方式属性
  4. 用空格数量表示层级关系

我工作中遇到的问题

大家估计在spring中主要都是读取yml文件,所以对于写yml文件的过程经历不太多,我的项目系统是自己的java框架,然后要集成另外的一个spring项目,当我的项目修改数据库信息的时候同时也要修改这个springboot项目的数据库配置信息,那么就存在一个对yml的读和写的过程,我经过百度后加上自己的代码,就得到了自己想要的效果;主要用到了ymal这个开源工具类;
maven依赖

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

读取

关键代码,ymal工具自动将yml文件转换为map结构的对象

//解析yml文件的关键类
        Yaml yml =null;
        try (FileInputStream in = new FileInputStream(file)){

            yml = new Yaml();
            obj = (Map)yml.load(in);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        Map<String,Object> springMap =(Map)obj.get("spring");

写入

关键代码,

try (FileWriter writer = new FileWriter(file)) {
            //writer.write(yml.dump(obj));
            writer.write(yml.dumpAsMap(obj));
           //writer.write(yml.dumpAs(obj, Tag.MAP, DumperOptions.FlowStyle.BLOCK));
           //可以自定义写入格式
            //writer.write(yml.dumpAs(obj, Tag.MAP, DumperOptions.FlowStyle.FLOW));
        } catch (IOException e) {
            e.printStackTrace();
        }

我用的是dumpAsMap方法,这个方法能够自动把map结构的对象转为yml文件的key:value的结构,map层级用两个空格表示,但是我的这个项目用了4个空格,所以后面我还得重新特殊处理一下;

完整代码,

因为我的主要目的是修改数据库配置信息,由于项目系统支持了很多类型的数据库,所以我要适配各种数据库;

@SpringBootTest
public class DemoTest {
    @Test
    public void readYmlTest()  {

        //要读的文件路径
        String filePath ="C:"+File.separator+"Users"+File.separator+"17247"+File.separator+"Desktop"+File.separator+"application-exclusive.yml";
        Map<String,Object> obj =null;
        File file = new File(filePath);

        //解析yml文件的关键类
        Yaml yml =null;
        try (FileInputStream in = new FileInputStream(file)){

            yml = new Yaml();
            obj = (Map)yml.load(in);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        Map<String,Object> springMap =(Map)obj.get("spring");


        String url = "jdbc:oracle:thin:@127.0.0.1:1521/orcl";
        //String url = "jdbc:dm://127.0.0.1:5236/DMSERVER?zeroDateTimeBehavior=convertToNull&useUnicode=true&characterEncoding=utf-8";
        String usesrname = "poc";
        String pwd = "ENC(w2PXuzg+U60Zs2MA/FouyQ==)";

        AEDatasourceFactory AeDatasourceFactory = new AEDatasourceFactory(url,usesrname,pwd);
        //根据不同数据库更新模板
        AeDatasourceFactory.updateDatasourceTemplet(springMap);
        try (FileWriter writer = new FileWriter(file)) {
            //writer.write(yml.dump(obj));
            //writer.write(yml.dumpAsMap(obj));
           writer.write(yml.dumpAs(obj, Tag.MAP, DumperOptions.FlowStyle.BLOCK));
            //writer.write(yml.dumpAs(obj, Tag.MAP, DumperOptions.FlowStyle.BLOCK));
        } catch (IOException e) {
            e.printStackTrace();
        }
        //重新读取文件调整空格
        StringBuffer buffer = new StringBuffer();
        String newLine =System.lineSeparator();
        try (BufferedReader input = new BufferedReader(
                new InputStreamReader(new FileInputStream(file), "utf-8"));) {
            String line;
            while ((line = input.readLine()) != null) {
                String lineTrim = line.trim();
                String pre ="";
                if(line.startsWith("  ")){
                    int length = line.length()-lineTrim.length();
                    pre = this.getSpaceByNum(length*2);
                }
                if(lineTrim.startsWith("- ")){
                    //有横杠的需要再加4个空格
                    pre = pre+this.getSpaceByNum(4);
                }
                buffer.append(pre+lineTrim);
                buffer.append(newLine);
            }
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        try (BufferedWriter writer = new BufferedWriter(
                new OutputStreamWriter(new FileOutputStream(filePath, false), "utf-8"))) {

            writer.write(buffer.toString());
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
    //获取指定数量的空格
    private String getSpaceByNum(int num){
        StringBuffer buffer = new StringBuffer();
        for(int i=0;i<num;i++){
            buffer.append(" ");
        }
        return buffer.toString();
    }

    
    private String getAEEncryptPassword(String input) {

        return input ;
    }
}

适配数据库工厂类

import java.util.LinkedHashMap;
import java.util.Map;

/**
 * AE数据源模板工厂类
 */
public class AEDatasourceFactory {
    //oracle数据库
    private final String ORACLE_TYPE="jdbc:oracle";
    //sqlserver数据库类型
    private final String SQLSERVER_TYPE="jdbc:oracle";
    //db2数据库
    private final String DB2_TYPE="jdbc:db2";
    //达梦数据库
    private final String DM_TYPE="jdbc:dm";
    //pg数据库
    private final String PG_TYPE="dbc:postgresql";
    //高斯数据库
    private final String GAUSS_TYPE="jdbc:zenith";

    String url;
    String username;
    String password;
    public AEDatasourceFactory(String url, String username, String password) {

        this.url=url;
        this.username=username;
        this.password=password;

    }

    /**
     * 获取更新数据源模板
     * @param springMap
     */
    public void updateDatasourceTemplet(Map<String,Object> springMap){
        Map<String,Object> dataSource = (Map<String,Object>)springMap.get("datasource");
        Map<String,Object> jpaMap = (Map<String,Object>)dataSource.get("jpa");
        if(jpaMap==null){
            //应该是jpa和datasource同级的,
            // 但是他们提供的可能是不同级的
            jpaMap = springMap.get("jpa")!=null?(Map<String,Object>)springMap.get("jpa"):new LinkedHashMap<>();
        }
        dataSource.clear();
        Map<String,Object> hikari = new LinkedHashMap<>();
        hikari.put("auto-commit",false);
        if(url.startsWith(ORACLE_TYPE) || url.startsWith(SQLSERVER_TYPE)){
            dataSource.put("type","com.zaxxer.hikari.HikariDataSource");
            dataSource.put("url",url);
            dataSource.put("username",username);
            dataSource.put("password",getAEEncryptPassword(password));
            dataSource.put("hikari",hikari);

        }else if(url.startsWith(DM_TYPE)){
            dataSource.put("url",url);
            dataSource.put("username",username);
            dataSource.put("password",getAEEncryptPassword(password));
            dataSource.put("driver-class-name","dm.jdbc.driver.DmDriver");
        }else if(url.startsWith(DB2_TYPE)){
            dataSource.put("type","com.zaxxer.hikari.HikariDataSource");
            dataSource.put("driver-class-name","com.ibm.db2.jcc.DB2Driver");
            dataSource.put("hikari",hikari);
        }else if(url.startsWith(GAUSS_TYPE)){
            dataSource.put("url",url);
            dataSource.put("username",username);
            dataSource.put("password",getAEEncryptPassword(password));
            dataSource.put("driver-class-name","com.huawei.gauss.jdbc.ZenithDriver");
        }else if(url.startsWith(PG_TYPE)){
            dataSource.put("type","com.zaxxer.hikari.HikariDataSource");
            dataSource.put("url",url);
            dataSource.put("username",username);
            dataSource.put("password",getAEEncryptPassword(password));
            dataSource.put("hikari",hikari);
            //pg没有jpa
            jpaMap=null;
        }
        if(jpaMap!=null){
            getJpaTemplet(jpaMap);
            springMap.put("jpa",jpaMap);
        }
    }
    private void getJpaTemplet(Map<String,Object> jpaMap){
        if(jpaMap==null){
            return;
        }
        jpaMap.clear();
        Map<String,Object> properties = new LinkedHashMap<>();
        if(url.startsWith(ORACLE_TYPE) || url.startsWith(SQLSERVER_TYPE)){

            jpaMap.put("database-platform","org.hibernate.dialect.Oracle12cDialect");
            jpaMap.put("database","ORACLE");
            jpaMap.put("show-sql",false);
            properties.put("hibernate.id.new_generator_mappings",true);
            properties.put("hibernate.connection.provider_disables_autocommit",true);
            properties.put("hibernate.cache.use_second_level_cache",false);
            properties.put("hibernate.cache.use_query_cache",false);
            properties.put("hibernate.generate_statistics",false);
            jpaMap.put("properties",properties);
        }else if(url.startsWith(GAUSS_TYPE)){
            //不知道为啥要用oracle的
            properties.put("hibernate.dialect","org.hibernate.dialect.Oracle12cDialect");
            jpaMap.put("properties",properties);
        }else if(url.startsWith(DM_TYPE)){
            properties.put("hibernate.dialect","org.hibernate.dialect.DmDialect");
            jpaMap.put("properties",properties);
        }else if(url.startsWith(PG_TYPE)){

        }else if(url.startsWith(DB2_TYPE)){
            properties.put("hibernate.dialect","com.diwork.intelliv.workbench.auth.dialect.CustomDB2Dialect");
            properties.put("hibernate.auto_quote_keyword",true);
            jpaMap.put("properties",properties);
            jpaMap.put("show-sql",true);
            Map<String,Object> hibernate = new LinkedHashMap<>();
            Map<String,Object> naming = new LinkedHashMap<>();
            naming.put("physical-strategy","org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl");
            hibernate.put("naming",naming);
            jpaMap.put("hibernate",hibernate);
        }
    }
    //密码加密方法
    private String getAEEncryptPassword(String input) {

        return input ;
    }
}

这样修改了指定的内容,而且还保证了文件的原格式,但有个问题是文件的注释会丢失;

posted @ 2020-08-24 21:39  菜鸡变小鸟  阅读(7472)  评论(0编辑  收藏  举报