基於ini配置檔案實現多維陣列資料的按行儲存和讀取

2021-06-23 02:34:53 字數 3005 閱讀 5017

需求是為乙個多維陣列物件的資料按行儲存到檔案,需要鍵值對區分層級,對每個物件描述清晰。類似的格式如下:

上圖中的資料對應的就是如下的陣列(php 語言):

$arr = array(

'10003' => array(

'id' => 10003,

'tokentime' => 400),

'10005' => array(

'id' => 10005,

'cookie' => array(

'num' => 20

),'vcode' => array(

'length' => 6

),),

);

每個id對應一條資料物件,但是這個資料物件可能是多維的資料,需要用檔案對使用者可讀性友好的儲存起來,這裡很容易就可以想到使用json格式也是可以的,將陣列json_encode後儲存到檔案,讀取的時候使用json_decode解析為陣列或物件即可。這確實是一種方便的辦法,但是本案例使用的就是這中按行儲存的格式。因此需要自行實現解析與儲存的過程。

通過上述格式的分析,可以很容易聯想到ini檔案的格式,中括號區分的是區塊,下面對應鍵值對,但是這裡有乙個注意點是每個區塊開頭的點浩(「.」)代表了區塊的層級關係,正式這種層級關係表明了陣列的多維性和認為可讀性,也是非常巧妙的一種方式。

但是,需要考慮的乙個細節問題是,php的parse_ini_file函式對ini檔案讀取時,如果區塊名稱相同,那麼會新的區塊內容會覆蓋之前的區塊。php官方手冊中介紹如下:

array parse_ini_file ( string $filename [, bool $process_sections = false [, int$scanner_mode = ini_scanner_normal ]] )

parse_ini_file() 載入乙個由 filename 指定的 ini 檔案,並將其中的設定作為乙個聯合陣列返回。

ini 檔案的結構和 php.ini 的相似。

引數filename

要解析的 ini 檔案的檔名。

process_sections

如果將最後的 process_sections 引數設為 true,將得到乙個多維陣列,包括了配置檔案中每一節的名稱和設定。process_sections 的預設值是 false。

scanner_mode

can either be ini_scanner_normal (default) or ini_scanner_raw. if ini_scanner_raw is supplied, then option values will not be parsed.

也就是[.10003]區塊中出現了[..cookie]區塊,此時讀取檔案後,[.10005]區塊內的[..cookie]區塊會覆蓋前者的內容,當然也可以不使用parse_ini_file函式,而選擇對檔案按行讀取進行判斷這樣也是可以的。此處本人還是使用了parse_ini_file函式,因為上述檔案格式算是標準ini檔案格式的一種擴充套件,因此直接使用可以馬上返回乙個陣列再對陣列進行處理來說還是更為方便。

寫入方式如下,直接先看**:

$ret = '';

return file_put_contents($path, $ret);

}private function readarrayrecursive($arr, &$str = '', $prefix, $level = 1)else}}

這裡實現的本質就是要根據乙個現有的多維陣列拼湊出乙個含有多維陣列層級關係清晰的字串,最終寫入到指定的檔案中。

在主呼叫函式中呼叫遞迴輔助函式,遞迴方式看起來形式簡潔,但是卻不易寫出來,特別是level引數和每次傳遞的最終拼湊的字串str引數,這兩個引數非常重要。首先字串為空,prefix指定初始字首,level層級為1,對陣列元素遍歷,然後每個元素判斷是否為陣列,若不為陣列直接拼湊字串,如果為陣列則先生成區塊名稱,將level遞增1後將該陣列遞迴,完成後level遞減1返回到當前層級。

讀取方式使用的策略是先用parse_ini_file函式讀取後,對陣列進行調整,調整方式也是可以使用遞迴來實現,但是既然寫入使用了遞迴,我就用棧模擬了遞迴呼叫實現了非遞迴的寫入方式:

//按section讀取

//進行同級歸併

$kstack = array(); //使用棧處理同級鍵名

$level = 0; //棧頂元素的層級

$clevel = 0; //遍歷時當前元素層級

continue;

continue;

}$clevel = self::getlevel($k);

if ($clevel > $level)elsewhile($kl != $clevel); //獲取所有比當前元素層級深的鍵名,最後乙個與當前元素同級

$upkey = array_pop($levelkeys);

foreach($levelkeys as $downkey)

//將當前元素與取出的最後乙個同級元素壓棧

array_push($kstack, $upkey, $k);

$level = $kl;}}

while(count($kstack) > 1)

foreach($kkarr as $down)

array_push($kstack, $kkup);}}

private function getlevel($key)

return $level;

}主要策略是用kstack棧暫存當前區塊下大於等於當前遍歷元素的level的元素的鍵名,最終遍歷完成之後,在對棧進行清理,返回最終清理完的陣列即可。

上述實現的方式只是一種策略,正如我之前提到的可以考慮使用json格式或者xml格式,或者就算使用ini格式也可以按行讀取而不使用parse_ini_file函式,因此實現方式多樣,而且本文這種方式也不一定好,謹在此記錄分享。

Shiro 二 基於 ini 配置檔案

完整 demo org.apache.shirogroupid shiro allartifactid 1.2.5version dependency 定義使用者 users 使用者名稱 z3admin,密碼 12345,角色 admin z3admin 12345,admin 使用者名稱 l4pr...

ini配置檔案讀寫實現

標頭檔案 pragma once class operateini 原始檔 include stdafx.h include operateini.h include include include include define size line 1024 每行最大長度 define size f...

讀寫配置檔案 ini

配置檔案中經常用到ini檔案,在vc中其函式分別為 其中個引數的意思 lpctstr lpstring 是鍵值,也就是變數的值,必須為lpctstr或cstring型別 lpctstr lpfilename 完整的ini檔案路徑名 lpctstr lpdefaut 如果沒有其前兩個引數值,則將此值賦...