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 ;
    }
}

這樣修改了指定的內容,而且還保證了文件的原格式,但有個問題是文件的注釋會丟失;


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM