那些年,優秀的配置檔案庫

tiny丶發表於2019-03-22

我大量使用過的配置檔案主要有以下幾種:

在這些中間,我最喜歡的三種格式是: lua、INI 和 YAML ,最不喜歡的是 JSON 。下面簡單的說說它們。

優秀的配置檔案

我認為 好的配置檔案 必須包含下面幾個因素:

1. 規則足夠簡單
2. 人類友好
在沒有任何輔助工具的情況下清晰可讀
3. 支援簡單的層級關係
4. 允許註釋

如果還包含下面幾點,則可以認為是 優秀的配置檔案

5. 易於解析(解析庫有多種語言實現)
6. 逐行解析
在資料不完整的情況下不影響解析
7. 支援巢狀的層級關係
8. 支援列表和字典
9. 支援型別

lua 和 python

在 lua 開發中,由於 lua 語言的特性,使用一個 lua 檔案作為配置檔案是很常見也很自然的事情。在使用 quick-cocos2d-x 進行遊戲開發的日子裡,我大量使用 lua 的這種特性,甚至直接在配置檔案中包含簡單的邏輯來替換 _G 中的全域性變數。而在使用這些配置檔案的時候,只需要簡單地 require 它們,lua 直譯器會幫我們搞定一切。

當然,lua 作為配置檔案的這種方便是 lua 直譯器提供的,這也限制了 lua 配置檔案的通用性。我們應該儘量在 lua 程式中使用 lua 作為配置檔案。離開這個框架,則不太合適了。

python 的情況也類似。在 python 中,我將一個 dict 直接 dump 成為字串,在使用這個配置檔案的時候,使用 eval 解析。顯然,這樣使用並沒有 lua 那樣方便。

嚴格來說,這兩種格式算不得配置檔案。因為它們在特定的語言範疇易用,但缺乏跨語言和跨環境的通用性。例如,如果需要在 Python 中解析 lua 檔案,可能需要自己寫 解析器 來實現。

然而,我們可以使用語言的解析器來解析它們,可以不需要任何外部庫可能直接使用它們,它們還完全符合我上面定義的 “好的配置檔案” 標準。在沒有其它選擇(或不願意進行選擇),不考慮跨語言的前提下,它們用起來是挺不錯的。

JSON —— 非常糟糕

由於 JavaScript 的流行,JSON 當然成了最適合 JavaScript 使用的配置檔案。JSON 可以在 JavaScript 中使用 eval() 或者 JSON.parse() 來解析,解析後的內容直接成為 JavaScript 的內建物件。

但是,其實 JSON 不適合作為配置檔案使用。根據上面我定義的 好的配置檔案 條件來看:JSON 規則簡單但不宜讀(尤其是複雜的沒有格式化過的 JSON),不支援註釋,也不能使用較為寬鬆的語法。

例如,下面這種多餘的逗號在 JSON 中被認為是錯誤的語法:

1
2
3
JSON.parse('[1, 2, 3,]')
// SyntaxError: JSON.parse: unexpected character at 
// line 1 column 10 of the JSON data

JSON 的確是在網頁和 API 中傳遞資訊的一種好格式,而且各種語言都有它的解析庫,但但並不適合做配置檔案。

.properties 和 INI

.properties 主要用在 JAVA 程式中,JAVA 內建對它的解析。它是一種簡單的配置檔案格式,規則大概只有下面幾條:

  1. 使用 = : 或者空格作為鍵值對的分隔符;
  2. 單引號和雙引號會作為值的一部分;
  3. 允許使用 # 作為註釋;
  4. 可以使用 \ 作為轉義符,用來轉義空格、換行和 Unicode 編碼。

因為如此簡單的格式,.properteis 基本上不需要進行任何解釋就能直接使用。也正因為它如此簡單,不支援層級關係,因此它並不能算做 好的配置檔案 。

INI 則相當於擴充套件版本的 .properties ,包含 .properties 的所有優點,去除了一些缺點,並且可以使用 section 來支援層級。它與 .properties 的主要區別如下:

  1. 支援 [section];
  2. 不使用空格作為分隔符;
  3. 允許在鍵名和值中直接包含空格(不需使用轉義符);
  4. 支援更多的轉義符。

INI 格式是 好的配置檔案 ,還包含 優秀的配置檔案 的一些特性。由於解析簡單,我們可以對它做一些擴充套件以符合我們的需求。

例如,我在 rookout 中對 ConfigParser 進行了一點點擴充套件,使得 ini 可以支援 [@list name] 這類特殊的 section ,將它們直接解析成 Python 中的 list。

XML 和 PLIST —— 虐心(也虐手)

XML 當然是 好的配置檔案 ,但它編輯起來太麻煩。即使是有 XML Notepad 這類軟體的存在,太多的尖括號和巢狀也讓手寫這種配置檔案變得艱難。同樣是由於太多的尖括號,讓我不願意閱讀它。

PLIST 是 XML 的子集,是 Apple 定義的配置檔案格式,在 Mac OS X 和 iOS 作業系統中得到大量的應用。PLIST 中直接包含型別資訊,因此解析 PLIST 可以直接得到確定的資料型別(甚至是字典和陣列)。
XCode 直接支援 PLIST 的編輯,但由於在 Apple 生態系統之外使用是在比較少,支援這種格式的編輯器和解析庫都比較有限。當然你可以把它當作純文字檔案來編輯,那就又碰到了 XML 的問題。

我曾經用 ActionScript3 寫過一個 PLIST 格式解析庫,由於 AS3 對 XML 的原生支援,所以完成這個解析器還是很簡單的工作。

同樣,由於太多的尖括號,導致在版本管理中對不同的檔案版本進行比較的時候並不太直觀。

總之,我不願意手寫這兩種配置檔案格式,機器生成倒是很好的選擇。

實際上,一些軟體的特定檔案格式就是基於 XML 的。例如 TexturePacker 的 tps 檔案格式。

YAML —— 堪稱完美

YAML: YAML Ain’t Markup Language 是為了替代 XML 而生。它在 Ruby 中被髮揚光大併為世人所知。下面摘抄一段關於 YAML 的評價,來自這裡 :

為什麼不是XML呢?因為:

  • YAML的可讀性好。
  • YAML和指令碼語言的互動性好。
  • YAML使用實現語言的資料型別。
  • YAML有一個一致的資訊模型。
  • YAML易於實現。

上面5條也就是XML不足的地方。同時,YAML也有XML的下列優點:

  • YAML可以基於流來處理;
  • YAML表達能力強,擴充套件性好。

總之,YAML試圖用一種比XML更敏捷的方式,來完成XML所完成的任務。

YAML 完全達到我上面提到的 優秀配置檔案 的標準,到目前為止,堪稱完美。

 

相關文章