INI檔案格式以及Java編碼實現讀取

來源:互聯網
上載者:User

標籤:ini   java   格式   讀取   

INI是 initialization的縮寫。INI檔案是一種輕量級的設定檔,廣泛地用於各種作業系統和軟體中。INI檔案是一種簡單的文字檔,基本結構很簡單、可讀性高,必要的元素只有兩種:section、property(包括name/key和value)。
曆史:在MS-DOS和16位Windows系統中,直到Windows ME為止,都是使用INI檔案作為作業系統設定檔(比如:win.ini, system.ini),用來配置驅動、字型、啟動項、等等等等。各種應用軟體也廣泛地採用INI檔案來儲存自己的配置資訊。
Windows NT之後,微軟開始採用和推廣註冊表來儲存配置資訊,並引導開發人員盡量使用註冊表。然而,由於註冊表不是跨作業系統可用的,所有很多應用程式還是喜歡並繼續使用INI檔案,就算有些不是以ini作為副檔名(比如conf、txt等),也是使用了類似的section、property兩種元素。
格式/元素: Property:一般是由“=”號分隔的key(或叫name)/value對。一個property佔用一行。例子:name  =  valuemyName  =  張三
Section:就是由若干個property的歸類和分組,一個section佔用一行,名字放在中括弧“[]”裡面。section定義後面的所有property都屬於這個section,直到下一個section出現為止。
大小寫:在windows中,大小寫是不敏感的。
注釋:windows中的注釋是以分號“;”開始的文字(Linux用井號“#”)
除了以上的標準定義之外,一些應用程式還支援和補充了其他擴充的格式: 空行:某些程式不允許有空行; 注釋:有些程式支援使用井號“#”做注釋的開頭;有些程式不允許注釋和section、property混在一行中; 重名:如有重名的property,有些程式取第一個,有些取最後一個,(section重名的話無所謂,一般就是合并他們的properties); 轉義符:有些程式支援轉義符,特別是反斜線“\”在行末作為兩行的串連符; Global properties:有些程式支援在第一個section標籤之前可以有properties,並把它們歸類為“global” section; 空格:大多數程式支援處理name/value前後的空格,以便文字對齊增強可讀性; 順序:絕大多數程式是不管section和property出現的順序的;
和其他類型設定檔的比較:xml, json, yaml檔案:他們都支援嵌套定義properties,但屬於重量級的設定檔,文法比較複雜。
Java編碼實現讀取:實現的功能:* 讀取 INI 檔案,存放到Map中

* 支援以‘#’或‘;’開頭的注釋;
* 支援行串連符(行末的‘\‘標記);
* 支援預設的global properties;
* 支援list格式(非name=value格式處理為list格式);
* 支援空行、name/value前後的空格;
* 如果有重名,取最後一個;
代碼詳情:
/** * 去除ini檔案中的注釋,以";"或"#"開頭,順便去除UTF-8等檔案的BOM頭 * @param source * @return */private static String removeIniComments(String source){String result = source;if(result.contains(";")){result = result.substring(0, result.indexOf(";"));}if(result.contains("#")){result = result.substring(0, result.indexOf("#"));}//去除UTF-8的BOM!!!用Windows中的編輯器儲存UTF-8檔案,在檔案的第一個字元就是這個!!!if(result.startsWith("\uFEFF")){ //result = result.substring(1);result = result.replace("\uFEFF", "");}return result.trim();}/** * 讀取 INI 檔案,存放到Map中 *  * 支援以‘#’或‘;’開頭的注釋; * 支援行串連符(行末的'\'標記); * 支援預設的global properties; * 支援list格式(非name=value格式處理為list格式); * 支援空行、name/value前後的空格; * 如果有重名,取最後一個; *  * 格式(例子)如下 *  * # 我是注釋 * ; 我也是注釋 *  * name0=value0  # 我是global properties * name10=value10 *  * [normal section] # 我是普通的section * name1=value1 # 我是name和value *  * [list section] # 我是只有value的section,以第一個是否包含'='為判斷標準 * value1 * value2 *  * @param fileName * @return Map<sectionName, object> object是一個Map(存放name=value對)或List(存放只有value的properties) */public static Map<String, Object> readIniFile(String fileName){Map<String, List<String>> listResult = new HashMap<>();Map<String, Object> result = new HashMap<>();String globalSection = "global"; //Map中儲存的global properties的keyFile file = new File(fileName);        BufferedReader reader = null;        try {            reader = new BufferedReader(new FileReader(file));        //reader = new BufferedReader(new InputStreamReader(new FileInputStream(file),"windows-1256"));            String str = null;            String currentSection = globalSection; //處理預設的section            List<String> currentProperties = new ArrayList<>();            boolean lineContinued = false;            String tempStr = null;                        //一次讀入一行(非空),直到讀入null為檔案結束            //先全部放到listResult<String, List>中            while ((str = reader.readLine()) != null) {            str = removeIniComments(str).trim(); //去掉尾部的注釋、去掉首尾空格                        if("".equals(str)||str==null){            continue;            }            //如果前一行包括了串連符'\'            if(lineContinued == true){            str = tempStr + str;            }                        //處理行串連符'\'            if(str.endsWith("\\")){            lineContinued = true;            tempStr = str.substring(0,str.length()-1);            continue;            }else {            lineContinued = false;}                        //是否一個新section開始了            if(str.startsWith("[") && str.endsWith("]")){            String newSection = str.substring(1, str.length()-1).trim();            //如果新section不是現在的section,則把當前section存進listResult中            if(!currentSection.equals(newSection)){            listResult.put(currentSection, currentProperties);            currentSection = newSection;                        //新section是否重複的section            //如果是,則使用原來的list來存放properties            //如果不是,則new一個List來存放properties            currentProperties=listResult.get(currentSection);            if(currentProperties==null){            currentProperties = new ArrayList<>();            }            }            }else{            currentProperties.add(str);            }            }                        //把最後一個section存進listResult中            listResult.put(currentSection, currentProperties);                        reader.close();        } catch (IOException e) {            e.printStackTrace();        } finally {            if (reader != null) {                try {                    reader.close();                } catch (IOException e1) {                }            }        }                //整理拆開name=value對,並存放到MAP中:        //從listResult<String, List>中,看各個list中的元素是否包含等號“=”,如果包含,則拆開並放到Map中        //整理後,把結果放進result<String, Object>中        for(String key : listResult.keySet()){        List<String> tempList = listResult.get(key);                //空section不放到結果裡面        if(tempList==null||tempList.size()==0){        continue;        }                if(tempList.get(0).contains("=")){ //name=value對,存放在MAP裡面        Map<String, String> properties = new HashMap<>();        for(String s : tempList){        int delimiterPos = s.indexOf("=");        //處理等號前後的空格        properties.put(s.substring(0,delimiterPos).trim(), s.substring(delimiterPos+1, s.length()).trim());        }        result.put(key, properties);        }else{ //只有value,則擷取原來的list        result.put(key, listResult.get(key));        }        }        return result;}@SuppressWarnings("unchecked")public static void main(String[] args) {Map<String, Object> ini = readIniFile("D:/test.ini");for(String k : ini.keySet()){System.out.println(k + ini.get(k));}System.out.println(((Map<String, String>)ini.get("myInfo")).get("myName"));}

test.ini檔案內容:
;我是#注釋# global sectiona=a_valueb = b_value[section1] #section1注釋c=c_valuec1=c1_valued=d_value0&d_value1[list_section1] ;section2注釋list1list2list3.1&list3.2&list3.3[section1] #重複的sectione = e_value=eeef=f_value[ myInfo ]myName=老許[list_section2]url1url2aldfjkjhlxmclk98u230jdslkmfsdlk2039840237509i09is0f980934285==234u093

測試結果:
list_section2[url1, url2aldfjkjhlxmclk98u230jdslkmfsdlk2039840237509i09is0f980934285==234u093]global{b=b_value, a=a_value}list_section1[list1, list2, list3.1&list3.2&list3.3]section1{f=f_value, d=d_value0&d_value1, e=e_value=eee, c1=c1_value, c=c_value}myInfo{myName=老許}老許


參考文檔:https://en.wikipedia.org/wiki/INI_file
(原創文章,轉載請註明轉自Clement-Xu的部落格)
和其他類型設定檔的比較:xml, json, yaml檔案:他們都支援嵌套定義properties,但屬於重量級的設定檔,文法比較複雜。

著作權聲明:本文為原創文章,轉載請註明轉自Clement-Xu的csdn部落格。

INI檔案格式以及Java編碼實現讀取

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.