1. 程式人生 > >Java中使用yaml格式配置檔案

Java中使用yaml格式配置檔案

yaml簡介

YAML是“YAML不是一種標記語言”的外語縮寫
“YAML Ain't Markup Language”

反正就是一種標記語言唄,她不像xml那樣繁瑣,有那麼多標籤,他的格式比較簡單,以資料為中心,側重點是資料.

先來一個yaml格式的配置

repo:
  GIT_ANDROID_ROOT: git/android/
  REPO_MANIFEST_ADDR: ssh://gerrit.example.com:29418/git/android/platform/manifest
  REPO_MANIFEST_BRANCH: master
  REPO_MANIFEST_FILE: default.
xml REPO_MIRROR: /home/mirror REPO_GROUP: '' REPO_GROUP_AMSS: amss,common REPO_GROUP_ANDROID: all,-amss build: ANDROID_TARGET_PRODUCT_LIST: civic ANDROID_BUILD_VARIANT_LIST: user ANDROID_TARGET_CARRIER_LIST: whole_netcom ANDROID_BUILD_TYPE: release ANDROID_EXTRA_BUILD_STEPS: null ANDROID_EXTRA_BUILD_COMBINATION: civic,eng,fn,android:civic,userdebug,fn,android ANNOUNCE_LIST: null

如何使用java來讀取寫入yaml檔案

這裡使用snakeyaml這個模組來解析寫入
maven的依賴座標是:

<!-- https://mvnrepository.com/artifact/org.yaml/snakeyaml -->
<dependency>
    <groupId>org.yaml</groupId>
    <artifactId>snakeyaml</artifactId>
    <version>1.21</version>
</dependency>

讀取是直接使用 yaml 物件中的load方法,會返回一個map物件的.然後遍歷這個map得到自己想要的資料就可以了.

    private Map parseYaml(Path cf) {
        Yaml yaml = new Yaml();
        try {
            return yaml.load(new FileInputStream(cf.toFile()));
        } catch (FileNotFoundException e) {
            //e.printStackTrace();
        }
        return null;
    }

當然,也可以定義一個實體類

然後是寫入,直接呼叫yaml物件的一個dump方法,他是可以把一個map寫入為yaml格式檔案的

    //我這個方法就是修改上面那個yaml檔案的 build下面的某些欄位的.
    public void updateBuild(Path cf, Map<String, String> map) {
        String secn = "build";
        try {
            DumperOptions dumperOptions = new DumperOptions();
            dumperOptions.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
            dumperOptions.setDefaultScalarStyle(DumperOptions.ScalarStyle.PLAIN);
            dumperOptions.setPrettyFlow(false);
            Yaml yaml = new Yaml(dumperOptions);
            Map m = yaml.load(new FileInputStream(cf.toFile()));
            if (m == null) {
                m = new LinkedHashMap();
            }
            if (m.containsKey(secn)) {
                Map<String, String> mm = (Map<String, String>) m.get(secn);
                mm.putAll(map);
            } else {
                m.put(secn, map);
            }
            yaml.dump(m, new OutputStreamWriter((new FileOutputStream(cf.toFile()))));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

寫入需要注意的地方是,要先把檔案中的內容讀取出來,然後新增 或 修改 map中的內容,然後把修改後的map在寫入到檔案.
如果不讀取會把之前的配置給覆蓋掉的.

DumperOptions介紹

這裡介紹一下DumperOptions的作用.
通過程式碼我們可以知道 yaml 檔案有幾種不同的格式,像上面那個就是平常我們比較喜歡用的格式.
在寫入的時候我們要設定為 DumperOptions.FlowStyle.BLOCK 格式才行.

    public enum FlowStyle {
        FLOW(Boolean.TRUE), BLOCK(Boolean.FALSE), AUTO(null);

        private Boolean styleBoolean;

        private FlowStyle(Boolean flowStyle) {
            styleBoolean = flowStyle;
        }

        public Boolean getStyleBoolean() {
            return styleBoolean;
        }

        @Override
        public String toString() {
            return "Flow style: '" + styleBoolean + "'";
        }
    }

DumperOptions的FlowStyle屬性

DumperOptions.FlowStyle.BLOCK格式的樣子

repo:
  GIT_ANDROID_ROOT: git/android/
  REPO_MANIFEST_ADDR: ssh://gerrit.example.com:29418/git/android/platform/manifest
  REPO_MANIFEST_BRANCH: master
  REPO_MANIFEST_FILE: default.xml
  REPO_MIRROR: /home/mirror
  REPO_GROUP: ''
  REPO_GROUP_AMSS: amss,common
  REPO_GROUP_ANDROID: all,-amss
build:
  ANDROID_TARGET_PRODUCT_LIST: zl1,civic
  ANDROID_BUILD_VARIANT_LIST: user
  ANDROID_TARGET_CARRIER_LIST: whole_netcom
  ANDROID_BUILD_TYPE: release
  ANDROID_EXTRA_BUILD_STEPS: null
  ANDROID_EXTRA_BUILD_COMBINATION: civic,eng,fn,android:civic,userdebug,fn,android
  ANNOUNCE_LIST: null

下面這個就是 DumperOptions.FlowStyle.FLOW 格式的.這種格式對我們來說看起來不太方便的.

{repo: {GIT_ANDROID_ROOT: git/android/, REPO_MANIFEST_ADDR: 'ssh://gerrit.example.com:29418/git/android/platform/manifest',
    REPO_MANIFEST_BRANCH: master, REPO_MANIFEST_FILE: default.xml, REPO_MIRROR: /home/mirror,
    REPO_GROUP: '', REPO_GROUP_AMSS: 'amss,common', REPO_GROUP_ANDROID: 'all,-amss'},
  build: {ANDROID_TARGET_PRODUCT_LIST: 'zl1,civic', ANDROID_BUILD_VARIANT_LIST: user,
    ANDROID_TARGET_CARRIER_LIST: whole_netcom, ANDROID_BUILD_TYPE: release, ANDROID_EXTRA_BUILD_STEPS: null,
    ANDROID_EXTRA_BUILD_COMBINATION: 'civic,eng,fn,android:civic,userdebug,fn,android',
    ANNOUNCE_LIST: null}}

DumperOptions.FlowStyle.AUTO 格式和 上面的FLOW估計是一樣的,因為設定了也沒見他變化.

DumperOptions的ScalarStyle屬性

DumperOptions中還有個ScalarStyle屬性,可以設定資料外面是否加上引號等.其中有如下四種,預設是PLAIN的效果

DOUBLE_QUOTED('"'), 
SINGLE_QUOTED('\''), 
LITERAL('|'), 
PLAIN(null);

DumperOptions.ScalarStyle.DOUBLE_QUOTED 雙引號

"repo":
  "GIT_ANDROID_ROOT": "git/android/"
  "REPO_MANIFEST_ADDR": "ssh://gerrit.example.com:29418/git/android/platform/manifest"
  "REPO_MANIFEST_BRANCH": "master"
  "REPO_MANIFEST_FILE": "default.xml"
  "REPO_MIRROR": "/home/mirror"
  "REPO_GROUP": ""
  "REPO_GROUP_AMSS": "amss,common"
  "REPO_GROUP_ANDROID": "all,-amss"
"build":
  "ANDROID_TARGET_PRODUCT_LIST": "zl1,civic"
  "ANDROID_BUILD_VARIANT_LIST": "user"
  "ANDROID_TARGET_CARRIER_LIST": "whole_netcom"
  "ANDROID_BUILD_TYPE": "release"
  "ANDROID_EXTRA_BUILD_STEPS": !!null "null"
  "ANDROID_EXTRA_BUILD_COMBINATION": "civic,eng,fn,android:civic,userdebug,fn,android"
  "ANNOUNCE_LIST": !!null "null"

DumperOptions.ScalarStyle.SINGLE_QUOTED 單引號


'repo':
  'GIT_ANDROID_ROOT': 'git/android/'
  'REPO_MANIFEST_ADDR': 'ssh://gerrit.example.com:29418/git/android/platform/manifest'
  'REPO_MANIFEST_BRANCH': 'master'
  'REPO_MANIFEST_FILE': 'default.xml'
  'REPO_MIRROR': '/home/mirror'
  'REPO_GROUP': ''
  'REPO_GROUP_AMSS': 'amss,common'
  'REPO_GROUP_ANDROID': 'all,-amss'
'build':
  'ANDROID_TARGET_PRODUCT_LIST': 'zl1,civic'
  'ANDROID_BUILD_VARIANT_LIST': 'user'
  'ANDROID_TARGET_CARRIER_LIST': 'whole_netcom'
  'ANDROID_BUILD_TYPE': 'release'
  'ANDROID_EXTRA_BUILD_STEPS': !!null 'null'
  'ANDROID_EXTRA_BUILD_COMBINATION': 'civic,eng,fn,android:civic,userdebug,fn,android'
  'ANNOUNCE_LIST': !!null 'null'

DumperOptions.ScalarStyle.FOLDED


"repo":
  "GIT_ANDROID_ROOT": >-
    git/android/
  "REPO_MANIFEST_ADDR": >-
    ssh://gerrit.example.com:29418/git/android/platform/manifest
  "REPO_MANIFEST_BRANCH": >-
    master
  "REPO_MANIFEST_FILE": >-
    default.xml
  "REPO_MIRROR": >-
    /home/mirror
  "REPO_GROUP": ""
  "REPO_GROUP_AMSS": >-
    amss,common
  "REPO_GROUP_ANDROID": >-
    all,-amss
"build":
  "ANDROID_TARGET_PRODUCT_LIST": >-
    zl1,civic
  "ANDROID_BUILD_VARIANT_LIST": >-
    user
  "ANDROID_TARGET_CARRIER_LIST": >-
    whole_netcom
  "ANDROID_BUILD_TYPE": >-
    release
  "ANDROID_EXTRA_BUILD_STEPS": !!null >-
    null
  "ANDROID_EXTRA_BUILD_COMBINATION": >-
    civic,eng,fn,android:civic,userdebug,fn,android
  "ANNOUNCE_LIST": !!null >-
    null

DumperOptions.ScalarStyle.LITERAL


"repo":
  "GIT_ANDROID_ROOT": |-
    git/android/
  "REPO_MANIFEST_ADDR": |-
    ssh://gerrit.example.com:29418/git/android/platform/manifest
  "REPO_MANIFEST_BRANCH": |-
    master
  "REPO_MANIFEST_FILE": |-
    default.xml
  "REPO_MIRROR": |-
    /home/mirror
  "REPO_GROUP": ""
  "REPO_GROUP_AMSS": |-
    amss,common
  "REPO_GROUP_ANDROID": |-
    all,-amss
"build":
  "ANDROID_TARGET_PRODUCT_LIST": |-
    zl1,civic
  "ANDROID_BUILD_VARIANT_LIST": |-
    user
  "ANDROID_TARGET_CARRIER_LIST": |-
    whole_netcom
  "ANDROID_BUILD_TYPE": |-
    release
  "ANDROID_EXTRA_BUILD_STEPS": !!null |-
    null
  "ANDROID_EXTRA_BUILD_COMBINATION": |-
    civic,eng,fn,android:civic,userdebug,fn,android
  "ANNOUNCE_LIST": !!null |-
    null